cobinstance.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,724 行 · 第 1/4 页
CPP
1,724 行
#include "StdAfx.h"
#include "CobEngine.h"
#include "CobFile.h"
#include "CobInstance.h"
#include "CobThread.h"
#ifndef _CONSOLE
#include <SDL_types.h>
#include "Game/GameHelper.h"
#include "LogOutput.h"
#include "Map/Ground.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Rendering/UnitModels/s3oParser.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Misc/RadarHandler.h"
#include "Sim/MoveTypes/AirMoveType.h"
#include "Sim/MoveTypes/MoveType.h"
#include "Sim/Projectiles/ExplosionGenerator.h"
#include "Sim/Projectiles/PieceProjectile.h"
#include "Sim/Projectiles/ProjectileHandler.h"
#include "Sim/Projectiles/Unsynced/BubbleProjectile.h"
#include "Sim/Projectiles/Unsynced/HeatCloudProjectile.h"
#include "Sim/Projectiles/Unsynced/MuzzleFlame.h"
#include "Sim/Projectiles/Unsynced/SmokeProjectile.h"
#include "Sim/Projectiles/Unsynced/WakeProjectile.h"
#include "Sim/Projectiles/Unsynced/WreckProjectile.h"
#include "Sim/Units/CommandAI/CommandAI.h"
#include "Sim/Units/CommandAI/Command.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/UnitTypes/TransportUnit.h"
#include "Sim/Weapons/PlasmaRepulser.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "Sound.h"
#include "Sync/SyncTracer.h"
#include "mmgr.h"
#endif
// Indices for set/get value
#define ACTIVATION 1 // set or get
#define STANDINGMOVEORDERS 2 // set or get
#define STANDINGFIREORDERS 3 // set or get
#define HEALTH 4 // get (0-100%)
#define INBUILDSTANCE 5 // set or get
#define BUSY 6 // set or get (used by misc. special case missions like transport ships)
#define PIECE_XZ 7 // get
#define PIECE_Y 8 // get
#define UNIT_XZ 9 // get
#define UNIT_Y 10 // get
#define UNIT_HEIGHT 11 // get
#define XZ_ATAN 12 // get atan of packed x,z coords
#define XZ_HYPOT 13 // get hypot of packed x,z coords
#define ATAN 14 // get ordinary two-parameter atan
#define HYPOT 15 // get ordinary two-parameter hypot
#define GROUND_HEIGHT 16 // get land height, 0 if below water
#define BUILD_PERCENT_LEFT 17 // get 0 = unit is built and ready, 1-100 = How much is left to build
#define YARD_OPEN 18 // set or get (change which plots we occupy when building opens and closes)
#define BUGGER_OFF 19 // set or get (ask other units to clear the area)
#define ARMORED 20 // set or get
/*#define WEAPON_AIM_ABORTED 21
#define WEAPON_READY 22
#define WEAPON_LAUNCH_NOW 23
#define FINISHED_DYING 26
#define ORIENTATION 27*/
#define IN_WATER 28
#define CURRENT_SPEED 29
//#define MAGIC_DEATH 31
#define VETERAN_LEVEL 32
#define ON_ROAD 34
#define MAX_ID 70
#define MY_ID 71
#define UNIT_TEAM 72
#define UNIT_BUILD_PERCENT_LEFT 73
#define UNIT_ALLIED 74
#define MAX_SPEED 75
#define CLOAKED 76
#define WANT_CLOAK 77
#define GROUND_WATER_HEIGHT 78 // get land height, negative if below water
#define UPRIGHT 79 // set or get
#define POW 80 // get
#define PRINT 81 // get, so multiple args can be passed
#define HEADING 82 // get
#define TARGET_ID 83 // get
#define LAST_ATTACKER_ID 84 // get
#define LOS_RADIUS 85 // set or get
#define AIR_LOS_RADIUS 86 // set or get
#define RADAR_RADIUS 87 // set or get
#define JAMMER_RADIUS 88 // set or get
#define SONAR_RADIUS 89 // set or get
#define SONAR_JAM_RADIUS 90 // set or get
#define SEISMIC_RADIUS 91 // set or get
#define DO_SEISMIC_PING 92 // get
#define CURRENT_FUEL 93 // set or get
#define TRANSPORT_ID 94 // get
#define SHIELD_POWER 95 // set or get
#define STEALTH 96 // set or get
#define CRASHING 97 // set or get, returns whether aircraft isCrashing state
#define CHANGE_TARGET 98 // set, the value it's set to determines the affected weapon
#define CEG_DAMAGE 99 // set
#define COB_ID 100 // get
#define PLAY_SOUND 101 // get, so multiple args can be passed
#define KILL_UNIT 102 // get KILL_UNIT(unitId, SelfDestruct=true, Reclaimed=false)
#define ALPHA_THRESHOLD 103 // set or get
#define SET_WEAPON_UNIT_TARGET 106 // get (fake set)
#define SET_WEAPON_GROUND_TARGET 107 // get (fake set)
// NOTE: [LUA0 - LUA9] are defined in CobThread.cpp as [110 - 119]
#define FLANK_B_MODE 120 // set or get
#define FLANK_B_DIR 121 // set or get, set is through get for multiple args
#define FLANK_B_MOBILITY_ADD 122 // set or get
#define FLANK_B_MAX_DAMAGE 123 // set or get
#define FLANK_B_MIN_DAMAGE 124 // set or get
#define WEAPON_RELOADSTATE 125 // get (with fake set)
#define WEAPON_RELOADTIME 126 // get (with fake set)
#define WEAPON_ACCURACY 127 // get (with fake set)
#define WEAPON_SPRAY 128 // get (with fake set)
#define WEAPON_RANGE 129 // get (with fake set)
#define WEAPON_PROJECTILE_SPEED 130 // get (with fake set)
// NOTE: shared variables use codes [1024 - 5119]
int CCobInstance::teamVars[MAX_TEAMS][TEAM_VAR_COUNT] = {{ 0 }};
int CCobInstance::allyVars[MAX_TEAMS][ALLY_VAR_COUNT] = {{ 0 }};
int CCobInstance::globalVars[GLOBAL_VAR_COUNT] = { 0 };
CCobInstance::CCobInstance(CCobFile& _script, CUnit* _unit)
: script(_script)
{
for (int i = 0; i < script.numStaticVars; ++i) {
staticVars.push_back(0);
}
for (unsigned int i = 0; i < script.pieceNames.size(); ++i) {
struct PieceInfo pi;
//init from model?
pi.coords[0] = 0; pi.coords[1] = 0; pi.coords[2] = 0;
pi.rot[0] = 0; pi.rot[1] = 0; pi.rot[2] = 0;
pi.name = script.pieceNames[i];
pi.updated = false;
pi.visible = true;
pieces.push_back(pi);
}
for (int i = 0; i < UNIT_VAR_COUNT; i++) {
unitVars[i] = 0;
}
unit = _unit;
// int mo = unit->pos.x;
yardOpen = false;
busy = false;
smoothAnim = unit->unitDef->smoothAnim;
}
CCobInstance::~CCobInstance(void)
{
//Can't delete the thread here because that would confuse the scheduler to no end
//Instead, mark it as dead. It is the function calling Tick that is responsible for delete.
//Also unregister all callbacks
for (list<CCobThread *>::iterator i = threads.begin(); i != threads.end(); ++i) {
(*i)->state = CCobThread::Dead;
(*i)->SetCallback(NULL, NULL, NULL);
}
// Remove us from possible animation ticking (should only be needed when anims.size() > 0
GCobEngine.RemoveInstance(this);
for (list<struct AnimInfo *>::iterator i = anims.begin(); i != anims.end(); ++i) {
//All threads blocking on animations can be killed safely from here since the scheduler does not
//know about them
for (list<CCobThread *>::iterator j = (*i)->listeners.begin(); j != (*i)->listeners.end(); ++j) {
delete *j;
}
delete *i;
}
}
int CCobInstance::Call(const string &fname)
{
vector<int> x;
return Call(fname, x, NULL, NULL, NULL);
}
int CCobInstance::Call(const string &fname, vector<int> &args)
{
return Call(fname, args, NULL, NULL, NULL);
}
int CCobInstance::Call(const string &fname, int p1)
{
vector<int> x;
x.push_back(p1);
return Call(fname, x, NULL, NULL, NULL);
}
int CCobInstance::Call(const string &fname, CBCobThreadFinish cb, void *p1, void *p2)
{
vector<int> x;
return Call(fname, x, cb, p1, p2);
}
int CCobInstance::Call(const string &fname, vector<int> &args, CBCobThreadFinish cb, void *p1, void *p2)
{
int fn = script.getFunctionId(fname);
if (fn == -1) {
//logOutput.Print("CobError: unknown function %s called by user", fname.c_str());
return -1;
}
return RealCall(fn, args, cb, p1, p2);
}
int CCobInstance::Call(int id)
{
vector<int> x;
return Call(id, x, NULL, NULL, NULL);
}
int CCobInstance::Call(int id, int p1)
{
vector<int> x;
x.push_back(p1);
return Call(id, x, NULL, NULL, NULL);
}
int CCobInstance::Call(int id, vector<int> &args)
{
return Call(id, args, NULL, NULL, NULL);
}
int CCobInstance::Call(int id, CBCobThreadFinish cb, void *p1, void *p2)
{
vector<int> x;
return Call(id, x, cb, p1, p2);
}
int CCobInstance::Call(int id, vector<int> &args, CBCobThreadFinish cb, void *p1, void *p2)
{
int fn = script.scriptIndex[id];
if (fn == -1) {
//logOutput.Print("CobError: unknown function index %d called by user", id);
if(cb){
(*cb)(0, p1, p2); //in case the function doesnt exist the callback should still be called
}
return -1;
}
return RealCall(fn, args, cb, p1, p2);
}
int CCobInstance::RawCall(int fn, vector<int> &args)
{
return RawCall(fn, args, NULL, NULL, NULL);
}
int CCobInstance::RawCall(int fn, vector<int> &args, CBCobThreadFinish cb, void *p1, void *p2)
{
if ((fn < 0) || (fn >= script.scriptNames.size())) {
if (cb) {
// in case the function doesnt exist the callback should still be called
(*cb)(0, p1, p2);
}
return -1;
}
return RealCall(fn, args, cb, p1, p2);
}
//Returns 0 if the call terminated. If the caller provides a callback and the thread does not terminate,
//it will continue to run. Otherwise it will be killed. Returns 1 in this case.
int CCobInstance::RealCall(int functionId, vector<int> &args, CBCobThreadFinish cb, void *p1, void *p2)
{
CCobThread *t = SAFE_NEW CCobThread(script, this);
t->Start(functionId, args, false);
#if COB_DEBUG > 0
if (COB_DEBUG_FILTER)
logOutput.Print("Calling %s:%s", script.name.c_str(), script.scriptNames[functionId].c_str());
#endif
int res = t->Tick(30);
t->CommitAnims(30);
//Make sure this is run even if the call terminates instantly
if (cb)
t->SetCallback(cb, p1, p2);
if (res == -1) {
unsigned int i = 0, argc = t->CheckStack(args.size());
//Retrieve parameter values from stack
for (; i < argc; ++i)
args[i] = t->GetStackVal(i);
//Set erroneous parameters to 0
for (; i < args.size(); ++i)
args[i] = 0;
delete t;
return 0;
}
else {
//It has already added itself to the correct scheduler (global for sleep, or local for anim)
return 1;
}
}
//Updates cur, returns 1 if destination was reached, 0 otherwise
int CCobInstance::MoveToward(int &cur, int dest, int speed)
{
if (dest > cur) {
cur += speed;
if (cur > dest) {
cur = dest;
return 1;
}
}
else {
cur -= speed;
if (cur < dest) {
cur = dest;
return 1;
}
}
return 0;
}
//Updates cur, returns 1 if destination was reached, 0 otherwise
int CCobInstance::TurnToward(int &cur, int dest, int speed)
{
short int delta = dest - cur;
if (delta > 0) {
if (delta <= speed) {
cur = dest;
return 1;
}
cur += speed;
}
else {
if (delta >= -speed) {
cur = dest;
return 1;
}
cur -= speed;
}
cur %= 65536;
//logOutput.Print("turning %d %d %d", cur, dest, speed);
return 0;
}
//Dest is not the final angle (obviously) but the final desired speed
//Returns 1 if the desired speed is 0 and it is reached, otherwise 0
//Speed is updated if it is not equal to dest
//Divisor is the deltatime, it is not added before the call because speed may have to be updated
int CCobInstance::DoSpin(int &cur, int dest, int &speed, int accel, int divisor)
{
//Check if we are not at the final speed
if (speed != dest) {
speed += accel * 30 / divisor; //TA obviously defines accelerations in speed/frame (at 30 fps)
if (accel > 0) {
if (speed > dest)
speed = dest; //We are accelerating, make sure we dont go past desired speed
}
else {
if (speed < dest)
speed = dest; //Decelerating
if (speed == 0)
return 1;
}
}
//logOutput.Print("Spinning with %d %d %d %d", dest, speed, accel, divisor);
cur += speed / divisor;
cur %= 65536;
return 0;
}
// Unblocks all threads waiting on this animation
void CCobInstance::UnblockAll(struct AnimInfo * anim)
{
list<CCobThread *>::iterator li;
for (li = anim->listeners.begin(); li != anim->listeners.end(); ++li) {
//Not sure how to do this more cleanly.. Will probably rewrite it
if (((*li)->state == CCobThread::WaitMove) ||((*li)->state == CCobThread::WaitTurn)) {
(*li)->state = CCobThread::Run;
GCobEngine.AddThread(*li);
}
else if ((*li)->state == CCobThread::Dead) {
delete *li;
}
else {
logOutput.Print("CobError: Turn/move listenener in strange state %d", (*li)->state);
}
}
}
//Called by the engine when we are registered as animating. If we return -1 it means that
//there is no longer anything animating
int CCobInstance::Tick(int deltaTime)
{
int done;
list<struct AnimInfo *>::iterator it = anims.begin();
list<struct AnimInfo *>::iterator cur;
while (it != anims.end()) {
//Advance it, so we can erase cur safely
cur = it++;
done = false;
pieces[(*cur)->piece].updated = true;
switch ((*cur)->type) {
case AMove:
done = MoveToward(pieces[(*cur)->piece].coords[(*cur)->axis], (*cur)->dest, (*cur)->speed / (1000 / deltaTime));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?