예제 #1
0
void CCobInstance::TransportDrop(const CUnit* unit, const float3& pos)
{
	vector<int> args;
	args.push_back(unit->id);
	args.push_back(PACKXZ(pos.x, pos.z));
	Call(COBFN_TransportDrop, args);
}
예제 #2
0
void CTransportCAI::UnloadDrop(Command& c) {

	//fly over and drop unit
	if(inCommand){
		if(!owner->cob->busy)
			//if(scriptReady)
			FinishCommand();
	} else {
		if(((CTransportUnit*)owner)->transported.empty()){
			FinishCommand();
			return;
		}

		float3 pos(c.params[0],c.params[1],c.params[2]); //head towards goal

		//note that taairmovetype must be modified to allow non stop movement through goals for this to work well
		if(goalPos.distance2D(pos)>20){
			SetGoal(pos,owner->pos);
			lastDropPos = pos;
		}

		if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){

			pos.y=ground->GetHeight(pos.x,pos.z);
			CUnit* unit=((CTransportUnit*)owner)->transported.front().unit;
			am->maxDrift=1;

			//if near target or have past it accidentally- drop unit
			if(owner->pos.distance2D(pos) < 40 || (((pos - owner->pos).Normalize()).distance(owner->frontdir.Normalize()) > 0.5 && owner->pos.distance2D(pos)< 205)) {
				am->dontLand=true;
				owner->cob->Call("EndTransport"); //test
				((CTransportUnit*)owner)->DetachUnitFromAir(unit,pos);
				dropSpots.pop_back();

				if (dropSpots.empty()) {
					float3 fix = owner->pos+owner->frontdir*200;
					SetGoal(fix,owner->pos);//move the transport away after last drop
				}
				FinishCommand();
			}
		} else {
			inCommand=true;
			scriptReady=false;
			StopMove();
			std::vector<int> args;
			args.push_back(((CTransportUnit*)owner)->transported.front().unit->id);
			args.push_back(PACKXZ(pos.x, pos.z));
			owner->cob->Call("TransportDrop",args,ScriptCallback,this,0);
		}
	}
}
예제 #3
0
int CUnitScript::GetUnitVal(int val, int p1, int p2, int p3, int p4)
{
	// may happen in case one uses Spring.GetUnitCOBValue (Lua) on a unit with CNullUnitScript
	if (!unit) {
		ShowScriptError("Error: no unit (in GetUnitVal)");
		return 0;
	}

#ifndef _CONSOLE
	switch (val)
	{
	case ACTIVATION:
		if (unit->activated)
			return 1;
		else
			return 0;
		break;
	case STANDINGMOVEORDERS:
		return unit->moveState;
		break;
	case STANDINGFIREORDERS:
		return unit->fireState;
		break;
	case HEALTH: {
		if (p1 <= 0)
			return int((unit->health / unit->maxHealth) * 100.0f);

		const CUnit* u = uh->GetUnit(p1);

		if (u == NULL)
			return 0;
		else
			return int((u->health / u->maxHealth) * 100.0f);
	}
	case INBUILDSTANCE:
		if (unit->inBuildStance)
			return 1;
		else
			return 0;
	case BUSY:
		if (busy)
			return 1;
		else
			return 0;
		break;
	case PIECE_XZ: {
		if (!PieceExists(p1)) {
			ShowScriptError("Invalid piecenumber for get piece_xz");
			break;
		}
		const float3 relPos = GetPiecePos(p1);
		const float3 absPos = unit->pos + unit->frontdir * relPos.z + unit->updir * relPos.y + unit->rightdir * relPos.x;
		return PACKXZ(absPos.x, absPos.z);
	}
	case PIECE_Y: {
		if (!PieceExists(p1)) {
			ShowScriptError("Invalid piecenumber for get piece_y");
			break;
		}
		const float3 relPos = GetPiecePos(p1);
		const float3 absPos = unit->pos + unit->frontdir * relPos.z + unit->updir * relPos.y + unit->rightdir * relPos.x;
		return int(absPos.y * COBSCALE);
	}
	case UNIT_XZ: {
		if (p1 <= 0)
			return PACKXZ(unit->pos.x, unit->pos.z);

		const CUnit* u = uh->GetUnit(p1);

		if (u == NULL)
			return PACKXZ(0, 0);
		else
			return PACKXZ(u->pos.x, u->pos.z);
	}
	case UNIT_Y: {
		if (p1 <= 0)
			return int(unit->pos.y * COBSCALE);

		const CUnit* u = uh->GetUnit(p1);

		if (u == NULL)
			return 0;
		else
			return int(u->pos.y * COBSCALE);
	}
	case UNIT_HEIGHT: {
		if (p1 <= 0)
			return int(unit->radius * COBSCALE);

		const CUnit* u = uh->GetUnit(p1);

		if (u == NULL)
			return 0;
		else
			return int(u->radius * COBSCALE);
	}
	case XZ_ATAN:
		return int(RAD2TAANG*math::atan2((float)UNPACKX(p1), (float)UNPACKZ(p1)) + 32768 - unit->heading);
	case XZ_HYPOT:
		return int(math::hypot((float)UNPACKX(p1), (float)UNPACKZ(p1)) * COBSCALE);
	case ATAN:
		return int(RAD2TAANG*math::atan2((float)p1, (float)p2));
	case HYPOT:
		return int(math::hypot((float)p1, (float)p2));
	case GROUND_HEIGHT:
		return int(ground->GetHeightAboveWater(UNPACKX(p1), UNPACKZ(p1)) * COBSCALE);
	case GROUND_WATER_HEIGHT:
		return int(ground->GetHeightReal(UNPACKX(p1), UNPACKZ(p1)) * COBSCALE);
	case BUILD_PERCENT_LEFT:
		return int((1.0f - unit->buildProgress) * 100);

	case YARD_OPEN:
		if (yardOpen)
			return 1;
		else
			return 0;
	case BUGGER_OFF:
		break;
	case ARMORED:
		if (unit->armoredState)
			return 1;
		else
			return 0;
	case VETERAN_LEVEL:
		return int(100 * unit->experience);
	case CURRENT_SPEED:
		return int(unit->speed.Length() * COBSCALE);
	case ON_ROAD:
		return 0;
	case IN_WATER:
		return (unit->pos.y < 0.0f) ? 1 : 0;
	case MAX_ID:
		return uh->MaxUnits()-1;
	case MY_ID:
		return unit->id;

	case UNIT_TEAM: {
		const CUnit* u = uh->GetUnit(p1);
		return (u != NULL)? unit->team : 0;
	}
	case UNIT_ALLIED: {
		const CUnit* u = uh->GetUnit(p1);

		if (u != NULL) {
			return teamHandler->Ally(unit->allyteam, u->allyteam) ? 1 : 0;
		}

		return 0;
	}
	case UNIT_BUILD_PERCENT_LEFT: {
		const CUnit* u = uh->GetUnit(p1);

		if (u != NULL) {
			return int((1.0f - u->buildProgress) * 100);
		}

		return 0;
	}
	case MAX_SPEED: {
		return int(unit->moveType->GetMaxSpeed() * COBSCALE);
	} break;
	case REVERSING: {
		CGroundMoveType* gmt = dynamic_cast<CGroundMoveType*>(unit->moveType);
		return ((gmt != NULL)? int(gmt->IsReversing()): 0);
	} break;
	case CLOAKED:
		return !!unit->isCloaked;
	case WANT_CLOAK:
		return !!unit->wantCloak;
	case UPRIGHT:
		return !!unit->upright;
	case POW:
		return int(math::pow(((float)p1)/COBSCALE,((float)p2)/COBSCALE)*COBSCALE);
	case PRINT:
		LOG("Value 1: %d, 2: %d, 3: %d, 4: %d", p1, p2, p3, p4);
		break;
	case HEADING: {
		if (p1 <= 0) {
			return unit->heading;
		}

		const CUnit* u = uh->GetUnit(p1);

		if (u != NULL) {
			return u->heading;
		}

		return -1;
	}
	case TARGET_ID: {
		if (unit->weapons[p1 - 1]) {
			const CWeapon* weapon = unit->weapons[p1 - 1];
			const TargetType tType = weapon->targetType;

			if (tType == Target_Unit)
				return unit->weapons[p1 - 1]->targetUnit->id;
			else if (tType == Target_None)
				return -1;
			else if (tType == Target_Pos)
				return -2;
			else // Target_Intercept
				return -3;
		}
		return -4; // weapon does not exist
	}

	case LAST_ATTACKER_ID:
		return unit->lastAttacker? unit->lastAttacker->id: -1;
	case LOS_RADIUS:
		return unit->realLosRadius;
	case AIR_LOS_RADIUS:
		return unit->realAirLosRadius;
	case RADAR_RADIUS:
		return unit->radarRadius;
	case JAMMER_RADIUS:
		return unit->jammerRadius;
	case SONAR_RADIUS:
		return unit->sonarRadius;
	case SONAR_JAM_RADIUS:
		return unit->sonarJamRadius;
	case SEISMIC_RADIUS:
		return unit->seismicRadius;

	case DO_SEISMIC_PING:
		float pingSize;
		if (p1 == 0) {
			pingSize = unit->seismicSignature;
		} else {
			pingSize = p1;
		}
		unit->DoSeismicPing(pingSize);
		break;

	case CURRENT_FUEL:
		return int(unit->currentFuel * float(COBSCALE));
	case TRANSPORT_ID:
		return unit->transporter?unit->transporter->id:-1;

	case SHIELD_POWER: {
		if (unit->shieldWeapon == NULL) {
			return -1;
		}
		const CPlasmaRepulser* shield = (CPlasmaRepulser*) unit->shieldWeapon;
		return int(shield->curPower * float(COBSCALE));
	}

	case STEALTH: {
		return unit->stealth ? 1 : 0;
	}
	case SONAR_STEALTH: {
		return unit->sonarStealth ? 1 : 0;
	}
	case CRASHING:
		return !!unit->crashing;
	case ALPHA_THRESHOLD: {
		return int(unit->alphaThreshold * 255);
	}

	case COB_ID: {
		if (p1 <= 0) {
			return unit->unitDef->cobID;
		} else {
			const CUnit* u = uh->GetUnit(p1);
			return ((u == NULL)? -1 : u->unitDef->cobID);
		}
	}

 	case PLAY_SOUND: {
 		// FIXME: this can currently only work for CCobInstance, because Lua can not get sound IDs
 		// (however, for Lua scripts there is already LuaUnsyncedCtrl::PlaySoundFile)
 		CCobInstance* cob = dynamic_cast<CCobInstance*>(this);
 		if (cob == NULL) {
 			return 1;
 		}
 		const CCobFile* script = cob->GetScriptAddr();
 		if (script == NULL) {
 			return 1;
 		}
		if ((p1 < 0) || (static_cast<size_t>(p1) >= script->sounds.size())) {
			return 1;
		}
		switch (p3) {	//who hears the sound
			case 0:		//ALOS
				if (!loshandler->InAirLos(unit->pos,gu->myAllyTeam)) { return 0; }
				break;
			case 1:		//LOS
				if (!(unit->losStatus[gu->myAllyTeam] & LOS_INLOS)) { return 0; }
				break;
			case 2:		//ALOS or radar
				if (!(loshandler->InAirLos(unit->pos,gu->myAllyTeam) || unit->losStatus[gu->myAllyTeam] & (LOS_INRADAR))) { return 0; }
				break;
			case 3:		//LOS or radar
				if (!(unit->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_INRADAR))) { return 0; }
				break;
			case 4:		//everyone
				break;
			case 5:		//allies
				if (unit->allyteam != gu->myAllyTeam) { return 0; }
				break;
			case 6:		//team
				if (unit->team != gu->myTeam) { return 0; }
				break;
			case 7:		//enemies
				if (unit->allyteam == gu->myAllyTeam) { return 0; }
				break;
		}
		if (p4 == 0) {
			Channels::General.PlaySample(script->sounds[p1], unit->pos, unit->speed, float(p2) / COBSCALE);
		} else {
			Channels::General.PlaySample(script->sounds[p1], float(p2) / COBSCALE);
		}
		return 0;
	}
	case SET_WEAPON_UNIT_TARGET: {
		const unsigned int weaponID = p1 - 1;
		const unsigned int targetID = p2;
		const bool userTarget = !!p3;

		if (weaponID >= unit->weapons.size()) {
			return 0;
		}

		CWeapon* weapon = unit->weapons[weaponID];

		if (weapon == NULL) {
			return 0;
		}

		//! if targetID is 0, just sets weapon->haveUserTarget
		//! to false (and targetType to None) without attacking
		CUnit* target = (targetID > 0)? uh->GetUnit(targetID): NULL;
		return (weapon->AttackUnit(target, userTarget) ? 1 : 0);
	}
	case SET_WEAPON_GROUND_TARGET: {
		const int weaponID = p1 - 1;
		const float3 pos = float3(float(UNPACKX(p2)),
		                          float(p3) / float(COBSCALE),
		                          float(UNPACKZ(p2)));
		const bool userTarget = !!p4;
		if ((weaponID < 0) || (static_cast<size_t>(weaponID) >= unit->weapons.size())) {
			return 0;
		}
		CWeapon* weapon = unit->weapons[weaponID];
		if (weapon == NULL) { return 0; }

		return weapon->AttackGround(pos, userTarget) ? 1 : 0;
	}
	case MIN:
		return std::min(p1, p2);
	case MAX:
		return std::max(p1, p2);
	case ABS:
		return abs(p1);
	case KSIN:
		return int(1024*math::sinf(TAANG2RAD*(float)p1));
	case KCOS:
		return int(1024*math::cosf(TAANG2RAD*(float)p1));
	case KTAN:
		return int(1024*math::tanf(TAANG2RAD*(float)p1));
	case SQRT:
		return int(math::sqrt((float)p1));
	case FLANK_B_MODE:
		return unit->flankingBonusMode;
	case FLANK_B_DIR:
		switch (p1) {
			case 1: return int(unit->flankingBonusDir.x * COBSCALE);
			case 2: return int(unit->flankingBonusDir.y * COBSCALE);
			case 3: return int(unit->flankingBonusDir.z * COBSCALE);
			case 4: unit->flankingBonusDir.x = (p2/(float)COBSCALE); return 0;
			case 5: unit->flankingBonusDir.y = (p2/(float)COBSCALE); return 0;
			case 6: unit->flankingBonusDir.z = (p2/(float)COBSCALE); return 0;
			case 7: unit->flankingBonusDir = float3(p2/(float)COBSCALE, p3/(float)COBSCALE, p4/(float)COBSCALE).Normalize(); return 0;
			default: return(-1);
		}
	case FLANK_B_MOBILITY_ADD:
		return int(unit->flankingBonusMobilityAdd * COBSCALE);
	case FLANK_B_MAX_DAMAGE:
		return int((unit->flankingBonusAvgDamage + unit->flankingBonusDifDamage) * COBSCALE);
	case FLANK_B_MIN_DAMAGE:
		return int((unit->flankingBonusAvgDamage - unit->flankingBonusDifDamage) * COBSCALE);
	case KILL_UNIT: {
		//! ID 0 is reserved for the script's owner
		CUnit* u = (p1 > 0)? uh->GetUnit(p1): this->unit;

		if (u == NULL) {
			return 0;
		}

		if (u->beingBuilt) {
			// no explosions and no corpse for units under construction
			u->KillUnit(false, true, NULL);
		} else {
			u->KillUnit(p2 != 0, p3 != 0, NULL);
		}

		return 1;
	}
	case WEAPON_RELOADSTATE: {
		const int np1 = -p1;
		if (p1 > 0 && static_cast<size_t>(p1) <= unit->weapons.size()) {
			return unit->weapons[p1-1]->reloadStatus;
		}
		else if (np1 > 0 && static_cast<size_t>(np1) <= unit->weapons.size()) {
			const int old = unit->weapons[np1 - 1]->reloadStatus;
			unit->weapons[np1 - 1]->reloadStatus = p2;
			return old;
		}
		else {
			return -1;
		}
	}
	case WEAPON_RELOADTIME: {
		const int np1 = -p1;
		if (p1 > 0 && static_cast<size_t>(p1) <= unit->weapons.size()) {
			return unit->weapons[p1-1]->reloadTime;
		}
		else if (np1 > 0 && static_cast<size_t>(np1) <= unit->weapons.size()) {
			const int old = unit->weapons[np1 - 1]->reloadTime;
			unit->weapons[np1 - 1]->reloadTime = p2;
			return old;
		}
		else {
			return -1;
		}
	}
	case WEAPON_ACCURACY: {
		const int np1 = -p1;
		if (p1 > 0 && static_cast<size_t>(p1) <= unit->weapons.size()) {
			return int(unit->weapons[p1-1]->accuracy * COBSCALE);
		}
		else if (np1 > 0 && static_cast<size_t>(np1) <= unit->weapons.size()) {
			const int old = unit->weapons[np1 - 1]->accuracy * COBSCALE;
			unit->weapons[np1 - 1]->accuracy = float(p2) / COBSCALE;
			return old;
		}
		else {
			return -1;
		}
	}
	case WEAPON_SPRAY: {
		const int np1 = -p1;
		if (p1 > 0 && static_cast<size_t>(p1) <= unit->weapons.size()) {
			return int(unit->weapons[p1-1]->sprayAngle * COBSCALE);
		}
		else if (np1 > 0 && static_cast<size_t>(np1) <= unit->weapons.size()) {
			const int old = unit->weapons[np1 - 1]->sprayAngle * COBSCALE;
			unit->weapons[np1 - 1]->sprayAngle = float(p2) / COBSCALE;
			return old;
		}
		else {
			return -1;
		}
	}
	case WEAPON_RANGE: {
		const int np1 = -p1;
		if (p1 > 0 && static_cast<size_t>(p1) <= unit->weapons.size()) {
			return int(unit->weapons[p1 - 1]->range * COBSCALE);
		}
		else if (np1 > 0 && static_cast<size_t>(np1) <= unit->weapons.size()) {
			const int old = unit->weapons[np1 - 1]->range * COBSCALE;
			unit->weapons[np1 - 1]->range = float(p2) / COBSCALE;
			return old;
		}
		else {
			return -1;
		}
	}
	case WEAPON_PROJECTILE_SPEED: {
		const int np1 = -p1;
		if (p1 > 0 && static_cast<size_t>(p1) <= unit->weapons.size()) {
			return int(unit->weapons[p1-1]->projectileSpeed * COBSCALE);
		}
		else if (np1 > 0 && static_cast<size_t>(np1) <= unit->weapons.size()) {
			const int old = unit->weapons[np1 - 1]->projectileSpeed * COBSCALE;
			unit->weapons[np1 - 1]->projectileSpeed = float(p2) / COBSCALE;
			return old;
		}
		else {
			return -1;
		}
	}
	case GAME_FRAME: {
		return gs->frameNum;
	}
	default:
		if ((val >= GLOBAL_VAR_START) && (val <= GLOBAL_VAR_END)) {
			return globalVars[val - GLOBAL_VAR_START];
		}
		else if ((val >= TEAM_VAR_START) && (val <= TEAM_VAR_END)) {
			return teamVars[unit->team][val - TEAM_VAR_START];
		}
		else if ((val >= ALLY_VAR_START) && (val <= ALLY_VAR_END)) {
			return allyVars[unit->allyteam][val - ALLY_VAR_START];
		}
		else if ((val >= UNIT_VAR_START) && (val <= UNIT_VAR_END)) {
			const int varID = val - UNIT_VAR_START;

			if (p1 == 0) {
				return unitVars[varID];
			}
			else if (p1 > 0) {
				// get the unit var for another unit
				const CUnit* u = uh->GetUnit(p1);

				if (u != NULL && u->script != NULL) {
					return u->script->unitVars[varID];
				}
			}
			else {
				// set the unit var for another unit
				p1 = -p1;

				CUnit* u = uh->GetUnit(p1);

				if (u != NULL && u->script != NULL) {
					u->script->unitVars[varID] = p2;
					return 1;
				}
			}
			return 0;
		}
		else {
			LOG_L(L_ERROR,
					"CobError: Unknown get constant %d (params = %d %d %d %d)",
					val, p1, p2, p3, p4);
		}
	}
#endif

	return 0;
}
예제 #4
0
void CLuaCob::CallFunction(const LuaHashString& name, const CUnit* unit,
                           int& argsCount, int args[MAX_LUA_COB_ARGS])
{
	static int callDepth = 0;
	if (callDepth >= 16) {
		logOutput.Print("CLuaCob::CallFunction() call overflow: %s\n",
		                name.GetString().c_str());
		args[0] = 0; // failure
		return;
	}

	lua_settop(L, 0);

	if (!name.GetGlobalFunc(L)) {
		lua_settop(L, 0);
		logOutput.Print("CLuaCob::CallFunction() missing function: %s\n",
		                name.GetString().c_str());
		args[0] = 0; // failure
		return;
	}

	lua_pushnumber(L, unit->id);
	lua_pushnumber(L, unit->unitDef->id);
	lua_pushnumber(L, unit->team);
	for (int a = 0; a < argsCount; a++) {
		lua_pushnumber(L, args[a]);
	}

	// call the routine
	callDepth++;
	const int* oldArgs = currentArgs;
	currentArgs = args;

	const bool error = !RunCallIn(name, 3 + argsCount, LUA_MULTRET);

	currentArgs = oldArgs;
	callDepth--;

	// bail on error
	if (error) {
		args[0] = 0; // failure
		return;
	}

	// get the results
	const int retArgs = min(lua_gettop(L), (MAX_LUA_COB_ARGS - 1));
	for (int a = 1; a <= retArgs; a++) {
		if (lua_isnumber(L, a)) {
			args[a] = (int)lua_tonumber(L, a);
		}
		else if (lua_isboolean(L, a)) {
			args[a] = lua_toboolean(L, a) ? 1 : 0;
		}
		else if (lua_istable(L, a)) {
			lua_rawgeti(L, a, 1);
			lua_rawgeti(L, a, 2);
			if (lua_isnumber(L, -2) && lua_isnumber(L, -1)) {
				const int x = (int)lua_tonumber(L, -2);
				const int z = (int)lua_tonumber(L, -1);
				args[a] = PACKXZ(x, z);
			} else {
				args[a] = 0;
			}
			lua_pop(L, 2);
		}
		else {
			args[a] = 0;
		}
	}

	args[0] = 1; // success
	return;
}
예제 #5
0
void CLuaRules::Cob2Lua(const LuaHashString& name, const CUnit* unit,
                        int& argsCount, int args[MAX_LUA_COB_ARGS])
{
	static int callDepth = 0;
	if (callDepth >= 16) {
		LOG_L(L_WARNING, "CLuaRules::Cob2Lua() call overflow: %s",
				name.GetString().c_str());
		args[0] = 0; // failure
		return;
	}

	LUA_CALL_IN_CHECK(L);

	const int top = lua_gettop(L);

	if (!lua_checkstack(L, 1 + 3 + argsCount)) {
		LOG_L(L_WARNING, "CLuaRules::Cob2Lua() lua_checkstack() error: %s",
				name.GetString().c_str());
		args[0] = 0; // failure
		lua_settop(L, top);
		return;
	}

	if (!name.GetGlobalFunc(L)) {
		LOG_L(L_WARNING, "CLuaRules::Cob2Lua() missing function: %s",
				name.GetString().c_str());
		args[0] = 0; // failure
		lua_settop(L, top);
		return;
	}

	lua_pushnumber(L, unit->id);
	lua_pushnumber(L, unit->unitDef->id);
	lua_pushnumber(L, unit->team);
	for (int a = 0; a < argsCount; a++) {
		lua_pushnumber(L, args[a]);
	}

	// call the routine
	callDepth++;
	const int* oldArgs = currentCobArgs;
	currentCobArgs = args;

	const bool error = !RunCallIn(name, 3 + argsCount, LUA_MULTRET);

	currentCobArgs = oldArgs;
	callDepth--;

	// bail on error
	if (error) {
		args[0] = 0; // failure
		lua_settop(L, top);
		return;
	}

	// get the results
	const int retArgs = std::min(lua_gettop(L) - top, (MAX_LUA_COB_ARGS - 1));
	for (int a = 1; a <= retArgs; a++) {
		const int index = (a + top);
		if (lua_isnumber(L, index)) {
			args[a] = lua_toint(L, index);
		}
		else if (lua_isboolean(L, index)) {
			args[a] = lua_toboolean(L, index) ? 1 : 0;
		}
		else if (lua_istable(L, index)) {
			lua_rawgeti(L, index, 1);
			lua_rawgeti(L, index, 2);
			if (lua_isnumber(L, -2) && lua_isnumber(L, -1)) {
				const int x = lua_toint(L, -2);
				const int z = lua_toint(L, -1);
				args[a] = PACKXZ(x, z);
			} else {
				args[a] = 0;
			}
			lua_pop(L, 2);
		}
		else {
			args[a] = 0;
		}
	}

	args[0] = 1; // success
	lua_settop(L, top);
	return;
}
예제 #6
0
void CTransportCAI::SlowUpdate(void)
{
	if(commandQue.empty()){
		CMobileCAI::SlowUpdate();
		return;
	}

	CTransportUnit* transport=(CTransportUnit*)owner;
	Command& c=commandQue.front();
	switch(c.id){
	case CMD_LOAD_UNITS:
		if(c.params.size()==1){		//load single unit
			if(transport->transportCapacityUsed >= owner->unitDef->transportCapacity){
				FinishCommand();
				return;
			}
			if(inCommand){
				if(!owner->cob->busy)
					FinishCommand();
				return;
			}
			CUnit* unit=uh->units[(int)c.params[0]];
			if(unit && CanTransport(unit)){
				toBeTransportedUnitId=unit->id;
				unit->toBeTransported=true;
				if(unit->mass+transport->transportMassUsed > owner->unitDef->transportMass){
					FinishCommand();
					return;
				}
				if(goalPos.distance2D(unit->pos)>10){
					float3 fix = unit->pos;
					SetGoal(fix,owner->pos,64);
				}
				if(unit->pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9){
					if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){		//handle air transports differently
						float3 wantedPos=unit->pos+UpVector*unit->model->height;
						SetGoal(wantedPos,owner->pos);
						am->dontCheckCol=true;
						am->ForceHeading(unit->heading);
						am->SetWantedAltitude(unit->model->height);
						am->maxDrift=1;
						//info->AddLine("cai dist %f %f %f",owner->pos.distance(wantedPos),owner->pos.distance2D(wantedPos),owner->pos.y-wantedPos.y);
						if(owner->pos.distance(wantedPos)<4 && abs(owner->heading-unit->heading)<50 && owner->updir.dot(UpVector)>0.995){
							am->dontCheckCol=false;
							am->dontLand=true;
							std::vector<int> args;
							args.push_back((int)(unit->model->height*65536));
							owner->cob->Call("BeginTransport",args);
							std::vector<int> args2;
							args2.push_back(0);
							args2.push_back((int)(unit->model->height*65536));
							owner->cob->Call("QueryTransport",args2);
							((CTransportUnit*)owner)->AttachUnit(unit,args2[0]);
							am->SetWantedAltitude(0);
							FinishCommand();
							return;
						}
					} else {
						inCommand=true;
						scriptReady=false;
						StopMove();
						std::vector<int> args;
						args.push_back(unit->id);
						owner->cob->Call("TransportPickup",args,ScriptCallback,this,0);
					}
				}
			} else {
				FinishCommand();
			}
		} else if(c.params.size()==4){		//load in radius
			if(lastCall==gs->frameNum)	//avoid infinite loops
				return;
			lastCall=gs->frameNum;
			float3 pos(c.params[0],c.params[1],c.params[2]);
			float radius=c.params[3];
			CUnit* unit=FindUnitToTransport(pos,radius);
			if(unit && ((CTransportUnit*)owner)->transportCapacityUsed < owner->unitDef->transportCapacity){
				Command c2;
				c2.id=CMD_LOAD_UNITS;
				c2.params.push_back(unit->id);
				c2.options=c.options | INTERNAL_ORDER;
				commandQue.push_front(c2);
				inCommand=false;
				SlowUpdate();
				return;
			} else {
				FinishCommand();
				return;
			}
		}
		break;
	case CMD_UNLOAD_UNITS:{
		if(lastCall==gs->frameNum)	//avoid infinite loops
			return;
		lastCall=gs->frameNum;
		if(((CTransportUnit*)owner)->transported.empty()){
			FinishCommand();
			return;
		}
		float3 pos(c.params[0],c.params[1],c.params[2]);
		float radius=c.params[3];
		float3 found;
		bool canUnload=FindEmptySpot(pos,max(16.0f,radius),((CTransportUnit*)owner)->transported.front().unit->radius,found);
		if(canUnload){
			Command c2;
			c2.id=CMD_UNLOAD_UNIT;
			c2.params.push_back(found.x);
			c2.params.push_back(found.y);
			c2.params.push_back(found.z);
			c2.options=c.options | INTERNAL_ORDER;
			commandQue.push_front(c2);
			SlowUpdate();
			return;
		} else {
			FinishCommand();
		}
		break;}
	case CMD_UNLOAD_UNIT:
		if(inCommand){
			if(!owner->cob->busy)
//			if(scriptReady)
				FinishCommand();
		} else {
			if(((CTransportUnit*)owner)->transported.empty()){
				FinishCommand();
				return;
			}
			float3 pos(c.params[0],c.params[1],c.params[2]);
			if(goalPos.distance2D(pos)>20){
				SetGoal(pos,owner->pos);
			}
			if(pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9){
				if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){		//handle air transports differently
					pos.y=ground->GetHeight(pos.x,pos.z);
					CUnit* unit=((CTransportUnit*)owner)->transported.front().unit;
					float3 wantedPos=pos+UpVector*unit->model->height;
					SetGoal(wantedPos,owner->pos);
					am->SetWantedAltitude(unit->model->height);
					am->maxDrift=1;
					if(owner->pos.distance(wantedPos)<8 && owner->updir.dot(UpVector)>0.99){
						am->dontLand=false;
						owner->cob->Call("EndTransport");
						((CTransportUnit*)owner)->DetachUnit(unit);
						float3 fix = owner->pos+owner->frontdir*20;
						SetGoal(fix,owner->pos);		//move the transport away slightly
						FinishCommand();
					}
				} else {
					inCommand=true;
					scriptReady=false;
					StopMove();
					std::vector<int> args;
					args.push_back(((CTransportUnit*)owner)->transported.front().unit->id);
					args.push_back(PACKXZ(pos.x, pos.z));
					owner->cob->Call("TransportDrop",args,ScriptCallback,this,0);
				}
			}
		}
		break;
	default:
		CMobileCAI::SlowUpdate();
		break;
	}
}
예제 #7
0
 int script_get(int type, int v1, int v2)
 {
     switch(type)
     {
         case VETERAN_LEVEL:
             return 0;
         case MIN_ID:
             return 0;
         case MAX_ID:
             return 254;
         case MY_ID:
             return 0;
         case UNIT_TEAM:		// returns team(player ID in TA) of unit given with parameter
             return 0;
         case UNIT_BUILD_PERCENT_LEFT:		// basically BUILD_PERCENT_LEFT, but comes with a unit parameter
             return 0;
         case UNIT_ALLIED:		// is unit given with parameter allied to the unit of the current COB script. 0=not allied, not zero allied
             return 1;
         case UNIT_IS_ON_THIS_COMP:		// indicates if the 1st parameter(a unit ID) is local to this computer
             return 1;
         case BUILD_PERCENT_LEFT:
             return 0;
         case ACTIVATION:
         case STANDINGMOVEORDERS:
         case STANDINGFIREORDERS:
         case HEALTH:
         case INBUILDSTANCE:
         case BUSY:
         case YARD_OPEN:
         case BUGGER_OFF:
         case ARMORED:
             return 0;//(int)port[type];
         case PIECE_XZ:
             {
                 Vec P = Mesh::instance()->getRelativePosition(v1);
                 return PACKXZ(P.x * 2.0f, P.z * 2.0f);
             }
         case PIECE_Y:
             {
                 Vec P = Mesh::instance()->getRelativePosition(v1);
                 return (int)(P.y * 2.0f) << 16;
             }
         case UNIT_XZ:
             return PACKXZ( 0.0f, 0.0f );
         case UNIT_Y:
             return (int)(0.0f) << 16;
         case UNIT_HEIGHT:
             return 0;//(int)(model->top * 2.0f) << 16;
         case XZ_ATAN:
             return (int)(atan2f( UNPACKX(v1) , UNPACKZ(v1) ) * RAD2TA) + 32768;
         case XZ_HYPOT:
             return (int)hypotf( UNPACKX(v1), UNPACKZ(v1) ) << 16;
         case ATAN:
             return (int)(atan2f(v1,v2) * RAD2TA );
         case HYPOT:
             return (int)hypotf(v1,v2);
         case GROUND_HEIGHT:
             return 0;
         default:
             LOG_DEBUG(LOG_PREFIX_SCRIPT << "GET unknown constant " << type);
     }
     return 0;
 }
예제 #8
0
int CCobInstance::GetUnitVal(int val, int p1, int p2, int p3, int p4)
{
#ifndef _CONSOLE
	switch(val)
	{
	case ACTIVATION:
		if (unit->activated)
			return 1;
		else
			return 0;
		break;
	case STANDINGMOVEORDERS:
		break;
	case STANDINGFIREORDERS:
		break;
	case HEALTH:
		return (int) ((unit->health/unit->maxHealth)*100.0f);
	case INBUILDSTANCE:
		if (unit->inBuildStance)
			return 1;
		else
			return 0;
	case BUSY:
		if (busy)
			return 1;
		else
			return 0;
		break;
	case PIECE_XZ:{
		if (!unit->localmodel->PieceExists(p1))
			GCobEngine.ShowScriptError("Invalid piecenumber for get piece_xz");
		float3 relPos = unit->localmodel->GetPiecePos(p1);
		float3 pos = unit->pos + unit->frontdir * relPos.z + unit->updir * relPos.y + unit->rightdir * relPos.x;
		return PACKXZ(pos.x, pos.z);}
	case PIECE_Y:{
		if (!unit->localmodel->PieceExists(p1))
			GCobEngine.ShowScriptError("Invalid piecenumber for get piece_y");
		float3 relPos = unit->localmodel->GetPiecePos(p1);
		float3 pos = unit->pos + unit->frontdir * relPos.z + unit->updir * relPos.y + unit->rightdir * relPos.x;
		return (int)(pos.y * SCALE);}
	case UNIT_XZ: {
		if (p1 == 0)	
			return PACKXZ(unit->pos.x, unit->pos.z);
		CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
		if (u == NULL)
			return PACKXZ(0,0);
		else
			return PACKXZ(u->pos.x, u->pos.z);}
	case UNIT_Y: {
		//logOutput.Print("Unit-y %d", p1);
		if (p1 == 0)
			return (int)(unit->pos.y * SCALE);
		CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
		if (u == NULL)
			return 0;
		else
			return (int)(u->pos.y * SCALE);}
	case UNIT_HEIGHT:{
		if (p1 == 0)
			return (int)(unit->radius * SCALE);
		CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
		if (u == NULL)
			return 0;
		else
			return (int)(u->radius * SCALE);}
	case XZ_ATAN:
		return (int)(TAANG2RAD*atan2((float)UNPACKX(p1), (float)UNPACKZ(p1)) + 32768 - unit->heading);
	case XZ_HYPOT:
		return (int)(hypot((float)UNPACKX(p1), (float)UNPACKZ(p1)) * SCALE);
	case ATAN:
		return (int)(TAANG2RAD*atan2((float)p1, (float)p2));
	case HYPOT:
		return (int)hypot((float)p1, (float)p2);
	case GROUND_HEIGHT:
		return (int)(ground->GetHeight(UNPACKX(p1), UNPACKZ(p1)) * SCALE);
	case BUILD_PERCENT_LEFT:
		return (int)((1 - unit->buildProgress) * 100);
	case YARD_OPEN:
		if (yardOpen)
			return 1;
		else
			return 0;
	case BUGGER_OFF:
		break;
	case ARMORED:
		if (unit->armoredState)
			return 1;
		else
			return 0;
	default:
		logOutput.Print("CobError: Unknown get constant %d", val);
	case VETERAN_LEVEL: 
		return (int)(100*unit->experience);
	case CURRENT_SPEED:
		if (unit->moveType)
			return (int)(unit->speed.Length()*SCALE);
		return 0;
	case ON_ROAD:
		return 0;
	case IN_WATER:
		return (unit->pos.y < 0.0f) ? 1 : 0;
	case MAX_ID:
		return MAX_UNITS-1;
	case MY_ID:
		return unit->id;
	case UNIT_TEAM:{
		CUnit *u = (p1 >= 0 && p1 < MAX_UNITS) ? uh->units[p1] : NULL;
		return u ? unit->team : 0; }
	case UNIT_ALLIED:{
		CUnit *u = (p1 >= 0 && p1 < MAX_UNITS) ? uh->units[p1] : NULL;
		if (u) return gs->Ally (unit->allyteam, u->allyteam) ? 1 : 0;
		return 0;}
	case UNIT_BUILD_PERCENT_LEFT:{
		CUnit *u = (p1 >= 0 && p1 < MAX_UNITS) ? uh->units[p1] : NULL;
		if (u) return (int)((1 - u->buildProgress) * 100);
		return 0;}
	case MAX_SPEED:
		if(unit->moveType){
			return int(unit->moveType->maxSpeed*SCALE);
		}
		break;
	}
#endif

	return 0;
}
예제 #9
0
void CTransportCAI::ExecuteUnloadUnit(Command &c)
{
	CTransportUnit* transport = (CTransportUnit*)owner;
	if (inCommand) {
		if (!owner->cob->busy) {
	//			if(scriptReady)
			FinishCommand();
		}
	}
	else {
		const std::list<CTransportUnit::TransportedUnit>& transList =
		  transport->transported;

		if (transList.empty()) {
			FinishCommand();
			return;
		}

		float3 pos(c.params[0], c.params[1], c.params[2]);
		if(goalPos.distance2D(pos) > 20){
			SetGoal(pos, owner->pos);
		}

		CUnit* unit = NULL;
		if (c.params.size() < 4) {
			unit = transList.front().unit;
		}
		else {
			const int unitID = (int)c.params[3];
			std::list<CTransportUnit::TransportedUnit>::const_iterator it;
			for (it = transList.begin(); it != transList.end(); ++it) {
				CUnit* carried = it->unit;
				if (unitID == carried->id) {
					unit = carried;
					break;
				}
			}
			if (unit == NULL) {
				FinishCommand();
				return;
			}
		}

		if (pos.distance2D(owner->pos) < (owner->unitDef->loadingRadius * 0.9f)) {
			CTAAirMoveType* am = dynamic_cast<CTAAirMoveType*>(owner->moveType);
			if (am != NULL) {
				// handle air transports differently
				pos.y = ground->GetHeight(pos.x, pos.z);
				const float3 wantedPos = pos + UpVector * unit->model->height;
				SetGoal(wantedPos, owner->pos);
				am->SetWantedAltitude(unit->model->height);
				am->maxDrift = 1;
				if ((owner->pos.distance(wantedPos) < 8) &&
				    (owner->updir.dot(UpVector) > 0.99f)) {
					am->dontLand = false;
					owner->cob->Call("EndTransport");
					transport->DetachUnit(unit);
					const float3 fix = owner->pos + owner->frontdir * 20;
					SetGoal(fix, owner->pos);		//move the transport away slightly
					FinishCommand();
				}
			} else {
				inCommand = true;
				scriptReady = false;
				StopMove();
				std::vector<int> args;
				args.push_back(transList.front().unit->id);
				args.push_back(PACKXZ(pos.x, pos.z));
				owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0);
			}
		}
	}
	return;
}
예제 #10
0
void CTransportCAI::UnloadLandFlood(Command& c) {
	//land, then release all units at once
	CTransportUnit* transport = (CTransportUnit*)owner;
	if (inCommand) {
			if (!owner->cob->busy) {
			  //if(scriptReady)
				FinishCommand();
			}
	} else {
		const std::list<CTransportUnit::TransportedUnit>& transList =
		  transport->transported;

		if (transList.empty()) {
			FinishCommand();
			return;
		}

		//check units are all carried
		CUnit* unit = NULL;
		if (c.params.size() < 4) {
			unit = transList.front().unit;
		} else {
			const int unitID = (int)c.params[3];
			std::list<CTransportUnit::TransportedUnit>::const_iterator it;
			for (it = transList.begin(); it != transList.end(); ++it) {
				CUnit* carried = it->unit;
				if (unitID == carried->id) {
					unit = carried;
					break;
				}
			}
			if (unit == NULL) {
				FinishCommand();
				return;
			}
		}

		//move to position
		float3 pos(c.params[0], c.params[1], c.params[2]);
		if (isFirstIteration) {
			if(goalPos.distance2D(pos) > 20)
				SetGoal(startingDropPos, owner->pos);
		}

		if (startingDropPos.distance2D(owner->pos) < (owner->unitDef->loadingRadius * 0.9f)) {
			//create aircraft movetype instance
			CTAAirMoveType* am = dynamic_cast<CTAAirMoveType*>(owner->moveType);

			if (am != NULL) {
				//lower to ground

				startingDropPos.y = ground->GetHeight(startingDropPos.x,startingDropPos.z);
				const float3 wantedPos = startingDropPos + UpVector * unit->model->height;
				SetGoal(wantedPos, owner->pos);
				am->SetWantedAltitude(1);
				am->maxDrift = 1;
				am->dontLand = false;

				//when on our way down start animations for unloading gear
				if (isFirstIteration) {
					owner->cob->Call("StartUnload");
				}
				isFirstIteration = false;

				//once at ground
				if (owner->pos.y - ground->GetHeight(wantedPos.x,wantedPos.z) < 8) {

					am->SetState(am->AIRCRAFT_LANDED);//nail it to the ground before it tries jumping up, only to land again...
					std::vector<int> args;
					args.push_back(transList.front().unit->id);
					args.push_back(PACKXZ(pos.x, pos.z));
					owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0); //call this so that other animations such as opening doors may be started
					transport->DetachUnitFromAir(unit,pos);

					FinishCommand();
					if (transport->transported.empty()) {
						am->dontLand = false;
						owner->cob->Call("EndTransport");
						am->UpdateLanded();
					}
				}
			} else {

				//land transports
				inCommand = true;
				scriptReady = false;
				StopMove();
				std::vector<int> args;
				args.push_back(transList.front().unit->id);
				args.push_back(PACKXZ(pos.x, pos.z));
				owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0);
				transport->DetachUnitFromAir(unit,pos);
				isFirstIteration = false;
				FinishCommand();
				if (transport->transported.empty())
					owner->cob->Call("EndTransport");
			}
		}
	}
	return;
}