Пример #1
0
/**
** Load the graphics for the unit-types.
*/
void LoadUnitTypes(void)
{
	CUnitType *type;

	for (size_t i = 0; i < UnitTypes.size(); ++i) {
		type = UnitTypes[i];

		//
		// Lookup icons.
		//
		type->Icon.Load();
		//
		// Lookup missiles.
		//
		type->Missile.Missile = MissileTypeByIdent(type->Missile.Name);
		if (!type->Explosion.Name.empty()) {
			type->Explosion.Missile = MissileTypeByIdent(type->Explosion.Name);
		}
		//
		// Lookup corpse.
		//
		if (!type->CorpseName.empty()) {
			type->CorpseType = UnitTypeByIdent(type->CorpseName);
		}

		//
		// Load Sprite
		//
		if (!type->Sprite) {
			ShowLoadProgress("Unit \"%s\"", type->Name.c_str());
			LoadUnitTypeSprite(type);
		}
	}
}
Пример #2
0
/* virtual */ void Spell_SpawnPortal::Parse(lua_State *l, int startIndex, int endIndex)
{
	for (int j = startIndex; j < endIndex; ++j) {
		lua_rawgeti(l, -1, j + 1);
		const char *value = LuaToString(l, -1);
		lua_pop(l, 1);
		++j;
		if (!strcmp(value, "portal-type")) {
			lua_rawgeti(l, -1, j + 1);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			this->PortalType = UnitTypeByIdent(value);
			if (!this->PortalType) {
				this->PortalType = 0;
				DebugPrint("unit type \"%s\" not found for spawn-portal.\n" _C_ value);
			}
		} else {
			LuaError(l, "Unsupported spawn-portal tag: %s" _C_ value);
		}
	}
	// Now, checking value.
	if (this->PortalType == NULL) {
		LuaError(l, "Use a unittype for spawn-portal (with portal-type)");
	}
}
Пример #3
0
/* virtual */ void Spell_Polymorph::Parse(lua_State *l, int startIndex, int endIndex)
{
	for (int j = startIndex; j < endIndex; ++j) {
		lua_rawgeti(l, -1, j + 1);
		const char *value = LuaToString(l, -1);
		lua_pop(l, 1);
		++j;
		if (!strcmp(value, "new-form")) {
			lua_rawgeti(l, -1, j + 1);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			this->NewForm = UnitTypeByIdent(value);
			if (!this->NewForm) {
				this->NewForm = 0;
				DebugPrint("unit type \"%s\" not found for polymorph spell.\n" _C_ value);
			}
			// FIXME: temp polymorphs? hard to do.
		} else if (!strcmp(value, "player-neutral")) {
			this->PlayerNeutral = 1;
			--j;
		} else if (!strcmp(value, "player-caster")) {
			this->PlayerNeutral = 2;
			--j;
		} else {
			LuaError(l, "Unsupported polymorph tag: %s" _C_ value);
		}
	}
	// Now, checking value.
	if (this->NewForm == NULL) {
		LuaError(l, "Use a unittype for polymorph (with new-form)");
	}
}
Пример #4
0
/**
**  Check if this upgrade or unit is available.
**
**  @param player  For this player available.
**  @param target  Unit or Upgrade.
**
**  @return        True if available, false otherwise.
*/
bool CheckDependByIdent(const CPlayer *player, const std::string &target)
{
	DependRule rule;

	//
	//  first have to check, if target is allowed itself
	//
	if (!strncmp(target.c_str(), "unit-", 5)) {
		// target string refers to unit-XXX
		rule.Kind.UnitType = UnitTypeByIdent(target);
		if (UnitIdAllowed(player, rule.Kind.UnitType->Slot) == 0) {
			return false;
		}
		rule.Type = DependRuleUnitType;
	} else if (!strncmp(target.c_str(), "upgrade-", 8)) {
		// target string refers to upgrade-XXX
		rule.Kind.Upgrade = CUpgrade::Get(target);
		if (UpgradeIdAllowed(player, rule.Kind.Upgrade->ID) != 'A') {
			return false;
		}
		rule.Type = DependRuleUpgrade;
	} else {
		DebugPrint("target `%s' should be unit-type or upgrade\n" _C_ target.c_str());
		return false;
	}

	return CheckDependByRule(player, rule);
}
Пример #5
0
/**
**  Show Map Location
**
**  @param l  Lua state.
*/
static int CclShowMapLocation(lua_State *l)
{
	// Put a unit on map, use its properties, except for
	// what is listed below

	LuaCheckArgs(l, 4);
	const char *unitname = LuaToString(l, 5);
	CUnitType *unitType = UnitTypeByIdent(unitname);
	if (!unitType) {
		DebugPrint("Unable to find UnitType '%s'" _C_ unitname);
		return 0;
	}
	CUnit *target = MakeUnit(*unitType, ThisPlayer);
	if (target != NULL) {
		target->Variable[HP_INDEX].Value = 0;
		target->tilePos.x = LuaToNumber(l, 1);
		target->tilePos.y = LuaToNumber(l, 2);
		target->TTL = GameCycle + LuaToNumber(l, 4);
		target->CurrentSightRange = LuaToNumber(l, 3);
		//Wyrmgus start
		UpdateUnitSightRange(*target);
		//Wyrmgus end
		MapMarkUnitSight(*target);
	} else {
		DebugPrint("Unable to allocate Unit");
	}
	return 0;
}
Пример #6
0
/* virtual */ void Spell_Summon::Parse(lua_State *l, int startIndex, int endIndex)
{
	for (int j = startIndex; j < endIndex; ++j) {
		const char *value = LuaToString(l, -1, j + 1);
		++j;
		if (!strcmp(value, "unit-type")) {
			value = LuaToString(l, -1, j + 1);
			this->UnitType = UnitTypeByIdent(value);
			if (!this->UnitType) {
				this->UnitType = 0;
				DebugPrint("unit type \"%s\" not found for summon spell.\n" _C_ value);
			}
		} else if (!strcmp(value, "time-to-live")) {
			this->TTL = LuaToNumber(l, -1, j + 1);
		} else if (!strcmp(value, "require-corpse")) {
			this->RequireCorpse = true;
			--j;
		} else if (!strcmp(value, "join-to-ai-force")) {
			this->JoinToAiForce = true;
			--j;
		} else {
			LuaError(l, "Unsupported summon tag: %s" _C_ value);
		}
	}
	// Now, checking value.
	if (this->UnitType == NULL) {
		LuaError(l, "Use a unittype for summon (with unit-type)");
	}
}
Пример #7
0
/**
**  Checks if dependencies are met.
**
**  @return true if the dependencies are met.
**
**  @param l  Lua state.
**  Argument 1: player
**  Argument 2: object which we want to check the dependencies of
*/
static int CclCheckDependency(lua_State *l)
{
	LuaCheckArgs(l, 2);
	const char *object = LuaToString(l, 2);
	lua_pop(l, 1);
	const int plynr = TriggerGetPlayer(l);
	if (plynr == -1) {
		LuaError(l, "bad player: %i" _C_ plynr);
	}
	const CPlayer *player = &Players[plynr];
	
	if (!strncmp(object, "unit-", 5)) {
		const CUnitType *unit_type = UnitTypeByIdent(object);
		if (!unit_type) {
			LuaError(l, "Invalid unit type: \"%s\"" _C_ object);
		}
		lua_pushboolean(l, CheckDependencies(unit_type, player));
	} else if (!strncmp(object, "upgrade-", 8)) {
		const CUpgrade *upgrade = CUpgrade::Get(object);
		if (!upgrade) {
			LuaError(l, "Invalid upgrade: \"%s\"" _C_ object);
		}
		lua_pushboolean(l, CheckDependencies(upgrade, player));
	} else {
		LuaError(l, "Invalid target of dependency check: \"%s\"" _C_ object);
	}

	return 1;
}
Пример #8
0
/**
** Load the graphics for the unit-types.
*/
void LoadUnitTypes()
{
	for (std::vector<CUnitType *>::size_type i = 0; i < UnitTypes.size(); ++i) {
		CUnitType &type = *UnitTypes[i];

		// Lookup icons.
		type.Icon.Load();
		// Lookup missiles.
		type.Missile.MapMissile();
		type.Explosion.MapMissile();

		// Lookup impacts
		for (int i = 0; i < ANIMATIONS_DEATHTYPES + 2; ++i) {
			type.Impact[i].MapMissile();
		}
		// Lookup corpse.
		if (!type.CorpseName.empty()) {
			type.CorpseType = UnitTypeByIdent(type.CorpseName);
		}
#ifndef DYNAMIC_LOAD
		// Load Sprite
		if (!type.Sprite) {
			ShowLoadProgress(_("Unit \"%s\""), type.Name.c_str());
			LoadUnitTypeSprite(type);
		}
#endif
		// FIXME: should i copy the animations of same graphics?
	}
}
Пример #9
0
/**
**  Check if this upgrade or unit is available.
**
**  @param player  For this player available.
**  @param target  Unit or Upgrade.
**
**  @return        True if available, false otherwise.
*/
std::string PrintDependencies(const CPlayer &player, const ButtonAction &button)
{
	std::string rules;

	//
	//  first have to check, if target is allowed itself
	//
	if (!strncmp(button.ValueStr.c_str(), "unit-", 5)) {
		// target string refers to unit-XXX
		const CUnitType *unit_type = UnitTypeByIdent(button.ValueStr);
		if (unit_type->Dependency) {
			rules = unit_type->Dependency->GetString();
		}
	} else if (!strncmp(button.ValueStr.c_str(), "upgrade-", 8)) {
		// target string refers to upgrade-XXX
		const CUpgrade *upgrade = CUpgrade::Get(button.ValueStr);
		if (upgrade->Dependency) {
			rules = upgrade->Dependency->GetString();
		}
	} else {
		DebugPrint("target '%s' should be unit-type or upgrade\n" _C_ button.ValueStr.c_str());
		return rules;
	}

	if (rules.empty()) {  //no dependencies found
		return rules;
	}

	rules.insert(0, _("Requirements:\n"));
	
	return rules;
}
Пример #10
0
/* virtual */ bool COrder_Build::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
	if (!strcmp(value, "building")) {
		++j;
		lua_rawgeti(l, -1, j + 1);
		this->BuildingUnit = CclGetUnitFromRef(l);
		lua_pop(l, 1);
	} else if (!strcmp(value, "range")) {
		++j;
		this->Range = LuaToNumber(l, -1, j + 1);
	} else if (!strcmp(value, "state")) {
		++j;
		this->State = LuaToNumber(l, -1, j + 1);
	} else if (!strcmp(value, "tile")) {
		++j;
		lua_rawgeti(l, -1, j + 1);
		CclGetPos(l, &this->goalPos.x , &this->goalPos.y);
		lua_pop(l, 1);
	} else if (!strcmp(value, "type")) {
		++j;
		this->Type = UnitTypeByIdent(LuaToString(l, -1, j + 1));
	} else {
		return false;
	}
	return true;
}
Пример #11
0
/* virtual */ bool COrder_TransformInto::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
	if (!strcmp(value, "type")) {
		++j;
		this->Type = UnitTypeByIdent(LuaToString(l, -1, j + 1));
	} else {
		return false;
	}
	return true;
}
Пример #12
0
/**
**  UnitType ID by identifier.
**
**  @param ident  The unit-type identifier.
**  @return       Unit-type ID (int) or -1 if not found.
*/
int UnitTypeIdByIdent(const std::string &ident)
{
	const CUnitType *type;

	if ((type = UnitTypeByIdent(ident))) {
		return type->Slot;
	}
	DebugPrint(" fix this %s\n" _C_ ident.c_str());
	Assert(0);
	return -1;
}
Пример #13
0
/* virtual */ bool COrder_UpgradeTo::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
	if (!strcmp(value, "type")) {
		++j;
		this->Type = UnitTypeByIdent(LuaToString(l, -1, j + 1));
	} else if (!strcmp(value, "ticks")) {
		++j;
		this->Ticks = LuaToNumber(l, -1, j + 1);
	} else {
		return false;
	}
	return true;
}
Пример #14
0
/**
**  Parse AiBuildQueue builing list
**
**  @param l     Lua state.
**  @param ai  PlayerAi pointer which should be filled with the data.
*/
static void CclParseBuildQueue(lua_State *l, PlayerAi *ai, int offset)
{
	if (!lua_istable(l, offset)) {
		LuaError(l, "incorrect argument");
	}

	Vec2i pos(-1, -1);

	const int args = lua_rawlen(l, offset);
	for (int k = 0; k < args; ++k) {
		lua_rawgeti(l, offset, k + 1);
		const char *value = LuaToString(l, -1);
		lua_pop(l, 1);
		++k;

		if (!strcmp(value, "onpos")) {
			lua_rawgeti(l, offset, k + 1);
			pos.x = LuaToNumber(l, -1);
			lua_pop(l, 1);
			++k;
			lua_rawgeti(l, offset, k + 1);
			pos.y = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else {

			//lua_rawgeti(l, j + 1, k + 1);
			//ident = LuaToString(l, -1);
			//lua_pop(l, 1);
			//++k;
			lua_rawgeti(l, offset, k + 1);
			const int made = LuaToNumber(l, -1);
			lua_pop(l, 1);
			++k;
			lua_rawgeti(l, offset, k + 1);
			const int want = LuaToNumber(l, -1);
			lua_pop(l, 1);

			AiBuildQueue queue;
			queue.Type = UnitTypeByIdent(value);
			queue.Want = want;
			queue.Made = made;
			queue.Pos = pos;

			ai->UnitTypeBuilt.push_back(queue);
			pos.x = -1;
			pos.y = -1;
		}
	}
}
Пример #15
0
void CUnitTypeDependency::ProcessConfigDataProperty(const std::pair<std::string, std::string> &property)
{
	const std::string &key = property.first;
	std::string value = property.second;
	if (key == "unit_type") {
		value = FindAndReplaceString(value, "_", "-");
		this->UnitType = UnitTypeByIdent(value);
		if (!this->UnitType) {
			fprintf(stderr, "Invalid unit type: \"%s\".\n", value.c_str());
		}
	} else if (key == "count") {
		this->Count = std::stoi(value);
	} else {
		fprintf(stderr, "Invalid unit type dependency property: \"%s\".\n", key.c_str());
	}
}
Пример #16
0
/* virtual */ bool COrder_Train::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
	if (!strcmp(value, "type")) {
		++j;
		this->Type = UnitTypeByIdent(LuaToString(l, -1, j + 1));
	//Wyrmgus start
	} else if (!strcmp(value, "player")) {
		++j;
		this->Player = LuaToNumber(l, -1, j + 1);
	//Wyrmgus end
	} else if (!strcmp(value, "ticks")) {
		++j;
		this->Ticks = LuaToNumber(l, -1, j + 1);
	} else {
		return false;
	}
	return true;
}
Пример #17
0
/**
**  Transform list of unit separed with coma to a true list.
*/
static std::vector<CUnitType *> getUnitTypeFromString(const std::string &list)
{
	std::vector<CUnitType *> res;

	if (list == "*") {
		return UnitTypes;
	}
	size_t begin = 1;
	size_t end = list.find(",", begin);
	while (end != std::string::npos) {
		std::string unitName = list.substr(begin, end - begin);
		begin = end + 1;
		end = list.find(",", begin);
		if (!unitName.empty()) {
			Assert(unitName[0] != ',');
			res.push_back(UnitTypeByIdent(unitName.c_str()));
		}
	}
	return res;
}
Пример #18
0
/* virtual */ void CAnimation_SpawnUnit::Action(CUnit &unit, int &/*move*/, int /*scale*/) const
{
	Assert(unit.Anim.Anim == this);

	const int offX = ParseAnimInt(unit, this->offXStr.c_str());
	const int offY = ParseAnimInt(unit, this->offYStr.c_str());
	const int range = ParseAnimInt(unit, this->rangeStr.c_str());
	const int playerId = ParseAnimInt(unit, this->playerStr.c_str());
	const SpawnUnit_Flags flags = (SpawnUnit_Flags)(ParseAnimFlags(unit, this->flagsStr.c_str()));

	CPlayer &player = Players[playerId];
	const Vec2i pos(unit.tilePos.x + offX, unit.tilePos.y + offY);
	CUnitType *type = UnitTypeByIdent(this->unitTypeStr.c_str());
	Assert(type);
	Vec2i resPos;
	DebugPrint("Creating a %s\n" _C_ type->Name.c_str());
	FindNearestDrop(*type, pos, resPos, LookingW);
	if (SquareDistance(pos, resPos) <= square(range)) {
		CUnit *target = MakeUnit(*type, &player);
		if (target != NULL) {
			target->tilePos = resPos;
			target->Place(resPos);
			if (flags & SU_Summoned) {
				target->Summoned = 1;
			}
			if ((flags & SU_JoinToAIForce) && unit.Player->AiEnabled) {
				int force = unit.Player->Ai->Force.GetForce(unit);
				if (force != -1) {
					unit.Player->Ai->Force[force].Insert(*target);
					target->GroupId = unit.GroupId;
					CommandDefend(*target, unit, FlushCommands);
				}
			}
			//DropOutOnSide(*target, LookingW, NULL);
		} else {
			DebugPrint("Unable to allocate Unit");
		}
	}
}
Пример #19
0
/**
**  Have unit of type.
**
**  @param ident   Identifier of unit-type that should be lookuped.
**
**  @return        How many exists, false otherwise.
**
**  @note This function should not be used during run time.
*/
int CPlayer::HaveUnitTypeByIdent(const std::string &ident) const
{
	return UnitTypesCount[UnitTypeByIdent(ident)->Slot];
}
Пример #20
0
/**
**  Define helper for AI.
**
**  @param l  Lua state.
**
**  @todo  FIXME: the first unit could be a list see ../doc/ccl/ai.html
*/
static int CclDefineAiHelper(lua_State *l)
{
	InitAiHelper(AiHelpers);

	const int args = lua_gettop(l);
	for (int j = 0; j < args; ++j) {
		if (!lua_istable(l, j + 1)) {
			LuaError(l, "incorrect argument");
		}
		const int subargs = lua_rawlen(l, j + 1);
		int k = 0;
		lua_rawgeti(l, j + 1, k + 1);
		const char *value = LuaToString(l, -1);
		lua_pop(l, 1);
		++k;

		//
		// Type build,train,research/upgrade.
		//
		int what;

		if (!strcmp(value, "build")) {
			what = -1;
		} else if (!strcmp(value, "train")) {
			what = -1;
		} else if (!strcmp(value, "upgrade")) {
			what = -1;
		} else if (!strcmp(value, "research")) {
			what = -1;
		} else if (!strcmp(value, "unit-limit")) {
			what = -1;
		} else if (!strcmp(value, "unit-equiv")) {
			what = 5;
		} else if (!strcmp(value, "repair")) {
			what = -1;
		} else {
			LuaError(l, "unknown tag: %s" _C_ value);
			what = -1;
		}
		if (what == -1) {
			continue;
		}
		//
		// Get the base unit type, which could handle the action.
		//

		// FIXME: support value as list!
		lua_rawgeti(l, j + 1, k + 1);
		value = LuaToString(l, -1);
		lua_pop(l, 1);
		++k;
		CUnitType *base = UnitTypeByIdent(value);
		if (!base) {
			LuaError(l, "unknown unittype: %s" _C_ value);
		}

		//
		// Get the unit types, which could be produced
		//
		for (; k < subargs; ++k) {
			lua_rawgeti(l, j + 1, k + 1);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			CUnitType *type = UnitTypeByIdent(value);
			if (!type) {
				LuaError(l, "unknown unittype: %s" _C_ value);
			}
			AiHelperInsert(AiHelpers.Equiv, base->Slot, *type);
			AiNewUnitTypeEquiv(base, type);
		}
	}
	return 0;
}
Пример #21
0
/**
**  Init AiHelper.
**
**  @param aiHelper  variable to initialise.
**
**  @todo missing Equiv initialisation.
*/
static void InitAiHelper(AiHelper &aiHelper)
{
	extern std::vector<ButtonAction *> UnitButtonTable;

	std::vector<CUnitType *> reparableUnits = getReparableUnits();
	std::vector<CUnitType *> supplyUnits = getSupplyUnits();
	std::vector<CUnitType *> mineUnits = getRefineryUnits();

	for (std::vector<CUnitType *>::const_iterator i = supplyUnits.begin(); i != supplyUnits.end(); ++i) {
		AiHelperInsert(aiHelper.UnitLimit, 0, **i);
	}

	for (int i = 1; i < MaxCosts; ++i) {
		for (std::vector<CUnitType *>::const_iterator j = mineUnits.begin(); j != mineUnits.end(); ++j) {
			if ((*j)->GivesResource == i) {
				/* HACK : we can't mine TIME then use 0 as 1 */
				AiHelperInsert(aiHelper.Refinery, i - 1, **j);
			}
		}

		for (std::vector<CUnitType *>::const_iterator d = UnitTypes.begin(); d != UnitTypes.end(); ++d) {
			CUnitType *type = *d;

			if (type->CanStore[i] > 0) {
				/* HACK : we can't store TIME then use 0 as 1 */
				AiHelperInsert(aiHelper.Depots, i - 1, **d);
			}
		}
	}

	for (size_t i = 0; i != UnitButtonTable.size(); ++i) {
		const ButtonAction &button = *UnitButtonTable[i];
		const std::vector<CUnitType *> &unitmask = getUnitTypeFromString(button.UnitMask);

		switch (button.Action) {
			case ButtonRepair :
				for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
					for (std::vector<CUnitType *>::const_iterator k = reparableUnits.begin(); k != reparableUnits.end(); ++k) {
						AiHelperInsert(aiHelper.Repair, (*k)->Slot, **j);
					}
				}
				break;
			case ButtonBuild: {
				CUnitType *buildingType = UnitTypeByIdent(button.ValueStr);

				for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
					AiHelperInsert(aiHelper.Build, buildingType->Slot, (**j));
				}
				break;
			}
			case ButtonTrain : {
				CUnitType *trainingType = UnitTypeByIdent(button.ValueStr);

				for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
					AiHelperInsert(aiHelper.Train, trainingType->Slot, (**j));
				}
				break;
			}
			case ButtonUpgradeTo : {
				CUnitType *upgradeToType = UnitTypeByIdent(button.ValueStr);

				for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
					AiHelperInsert(aiHelper.Upgrade, upgradeToType->Slot, **j);
				}
				break;
			}
			case ButtonResearch : {
				int researchId = UpgradeIdByIdent(button.ValueStr);

				for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
					AiHelperInsert(aiHelper.Research, researchId, **j);
				}
				break;
			}
			default:
				break;
		}
	}
}
Пример #22
0
/**
** Define an AI player.
**
**  @param l  Lua state.
*/
static int CclDefineAiPlayer(lua_State *l)
{
	const unsigned int playerIdx = LuaToNumber(l, 0 + 1);

	Assert(playerIdx <= PlayerMax);
	DebugPrint("%p %d\n" _C_(void *)Players[playerIdx].Ai _C_ Players[playerIdx].AiEnabled);
	// FIXME: lose this:
	// Assert(!Players[playerIdx].Ai && Players[playerIdx].AiEnabled);

	PlayerAi *ai = Players[playerIdx].Ai = new PlayerAi;
	ai->Player = &Players[playerIdx];

	// Parse the list: (still everything could be changed!)
	const int args = lua_gettop(l);
	for (int j = 1; j < args; ++j) {
		const char *value = LuaToString(l, j + 1);
		++j;

		if (!strcmp(value, "ai-type")) {
			const char *aiName = LuaToString(l, j + 1);
			CAiType *ait = GetAiTypesByName(aiName);
			if (ait == NULL) {
				lua_pushfstring(l, "ai-type not found: %s", aiName);
			}
			ai->AiType = ait;
			ai->Script = ait->Script;
		} else if (!strcmp(value, "script")) {
			ai->Script = LuaToString(l, j + 1);
		} else if (!strcmp(value, "script-debug")) {
			ai->ScriptDebug = LuaToBoolean(l, j + 1);
		} else if (!strcmp(value, "sleep-cycles")) {
			ai->SleepCycles = LuaToNumber(l, j + 1);
		} else if (!strcmp(value, "force")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			lua_rawgeti(l, j + 1, 0 + 1);
			const int cclforceIdx = LuaToNumber(l, -1);
			UNUSED(cclforceIdx);
			const int forceIdx = ai->Force.FindFreeForce(AiForceRoleDefault);
			lua_pop(l, 1);

			for (int k = 1; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *value = LuaToString(l, -1);
				lua_pop(l, 1);
				++k;
				if (!strcmp(value, "complete")) {
					ai->Force[forceIdx].Completed = true;
					--k;
				} else if (!strcmp(value, "recruit")) {
					ai->Force[forceIdx].Completed = false;
					--k;
				} else if (!strcmp(value, "attack")) {
					ai->Force[forceIdx].Attacking = true;
					--k;
				} else if (!strcmp(value, "defend")) {
					ai->Force[forceIdx].Defending = true;
					--k;
				} else if (!strcmp(value, "role")) {
					lua_rawgeti(l, j + 1, k + 1);
					value = LuaToString(l, -1);
					lua_pop(l, 1);
					if (!strcmp(value, "attack")) {
						ai->Force[forceIdx].Role = AiForceRoleAttack;
					} else if (!strcmp(value, "defend")) {
						ai->Force[forceIdx].Role = AiForceRoleDefend;
					} else {
						LuaError(l, "Unsupported force tag: %s" _C_ value);
					}
				} else if (!strcmp(value, "types")) {
					lua_rawgeti(l, j + 1, k + 1);
					if (!lua_istable(l, -1)) {
						LuaError(l, "incorrect argument");
					}
					const int subsubargs = lua_rawlen(l, -1);
					for (int subk = 0; subk < subsubargs; ++subk) {
						lua_rawgeti(l, -1, subk + 1);
						const int num = LuaToNumber(l, -1);
						lua_pop(l, 1);
						++subk;
						lua_rawgeti(l, -1, subk + 1);
						const char *ident = LuaToString(l, -1);
						lua_pop(l, 1);
						AiUnitType queue;

						queue.Want = num;
						queue.Type = UnitTypeByIdent(ident);
						ai->Force[forceIdx].UnitTypes.push_back(queue);
					}
					lua_pop(l, 1);
				} else if (!strcmp(value, "units")) {
					lua_rawgeti(l, j + 1, k + 1);
					if (!lua_istable(l, -1)) {
						LuaError(l, "incorrect argument");
					}
					const int subsubargs = lua_rawlen(l, -1);
					for (int subk = 0; subk < subsubargs; ++subk) {
						lua_rawgeti(l, -1, subk + 1);
						const int num = LuaToNumber(l, -1);
						lua_pop(l, 1);
						++subk;
#if 0
						lua_rawgeti(l, -1, subk + 1);
						const char *ident = LuaToString(l, -1);
						UNUSED(ident);
						lua_pop(l, 1);
#endif
						ai->Force[forceIdx].Units.Insert(&UnitManager.GetSlotUnit(num));
					}
					lua_pop(l, 1);
				} else if (!strcmp(value, "state")) {
					lua_rawgeti(l, j + 1, k + 1);
					ai->Force[forceIdx].State = AiForceAttackingState(LuaToNumber(l, -1));
					lua_pop(l, 1);
				} else if (!strcmp(value, "goalx")) {
					lua_rawgeti(l, j + 1, k + 1);
					ai->Force[forceIdx].GoalPos.x = LuaToNumber(l, -1);
					lua_pop(l, 1);
				} else if (!strcmp(value, "goaly")) {
					lua_rawgeti(l, j + 1, k + 1);
					ai->Force[forceIdx].GoalPos.y = LuaToNumber(l, -1);
					lua_pop(l, 1);
				} else if (!strcmp(value, "must-transport")) {
					// Keep for backward compatibility
				} else {
					LuaError(l, "Unsupported tag: %s" _C_ value);
				}
			}
		} else if (!strcmp(value, "reserve")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *type = LuaToString(l, -1);
				lua_pop(l, 1);
				++k;
				lua_rawgeti(l, j + 1, k + 1);
				int num = LuaToNumber(l, -1);
				lua_pop(l, 1);
				const int resId = GetResourceIdByName(l, type);
				ai->Reserve[resId] = num;
			}
		} else if (!strcmp(value, "used")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *type = LuaToString(l, -1);
				lua_pop(l, 1);
				++k;
				lua_rawgeti(l, j + 1, k + 1);
				const int num = LuaToNumber(l, -1);
				lua_pop(l, 1);
				const int resId = GetResourceIdByName(l, type);
				ai->Used[resId] = num;
			}
		} else if (!strcmp(value, "needed")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *type = LuaToString(l, -1);
				lua_pop(l, 1);
				++k;
				lua_rawgeti(l, j + 1, k + 1);
				const int num = LuaToNumber(l, -1);
				lua_pop(l, 1);
				const int resId = GetResourceIdByName(l, type);
				ai->Needed[resId] = num;
			}
		} else if (!strcmp(value, "collect")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *type = LuaToString(l, -1);
				lua_pop(l, 1);
				++k;
				lua_rawgeti(l, j + 1, k + 1);
				const int num = LuaToNumber(l, -1);
				lua_pop(l, 1);
				const int resId = GetResourceIdByName(l, type);
				ai->Collect[resId] = num;
			}
		} else if (!strcmp(value, "need-mask")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *type = LuaToString(l, -1);
				lua_pop(l, 1);
				const int resId = GetResourceIdByName(l, type);
				ai->NeededMask |= (1 << resId);
			}
		} else if (!strcmp(value, "need-supply")) {
			ai->NeedSupply = true;
			--j;
		} else if (!strcmp(value, "exploration")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				Vec2i pos;

				lua_rawgeti(l, j + 1, k + 1);
				if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 3) {
					LuaError(l, "incorrect argument");
				}
				lua_rawgeti(l, -1, 1);
				pos.x = LuaToNumber(l, -1);
				lua_pop(l, 1);
				lua_rawgeti(l, -1, 2);
				pos.y = LuaToNumber(l, -1);
				lua_pop(l, 1);
				lua_rawgeti(l, -1, 3);
				const int mask = LuaToNumber(l, -1);
				lua_pop(l, 1);
				lua_pop(l, 1);
				AiExplorationRequest queue(pos, mask);
				ai->FirstExplorationRequest.push_back(queue);
			}
		} else if (!strcmp(value, "last-exploration-cycle")) {
			ai->LastExplorationGameCycle = LuaToNumber(l, j + 1);
		} else if (!strcmp(value, "last-can-not-move-cycle")) {
			ai->LastCanNotMoveGameCycle = LuaToNumber(l, j + 1);
		} else if (!strcmp(value, "unit-type")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			int i = 0;
			if (subargs) {
				ai->UnitTypeRequests.resize(subargs / 2);
			}
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *ident = LuaToString(l, -1);
				lua_pop(l, 1);
				++k;
				lua_rawgeti(l, j + 1, k + 1);
				const int count = LuaToNumber(l, -1);
				lua_pop(l, 1);
				ai->UnitTypeRequests[i].Type = UnitTypeByIdent(ident);
				ai->UnitTypeRequests[i].Count = count;
				++i;
			}
		} else if (!strcmp(value, "upgrade")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *ident = LuaToString(l, -1);
				lua_pop(l, 1);
				ai->UpgradeToRequests.push_back(UnitTypeByIdent(ident));
			}
		} else if (!strcmp(value, "research")) {
			if (!lua_istable(l, j + 1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, j + 1);
			for (int k = 0; k < subargs; ++k) {
				lua_rawgeti(l, j + 1, k + 1);
				const char *ident = LuaToString(l, -1);
				lua_pop(l, 1);
				ai->ResearchRequests.push_back(CUpgrade::Get(ident));
			}
		} else if (!strcmp(value, "building")) {
			CclParseBuildQueue(l, ai, j + 1);
		} else if (!strcmp(value, "repair-building")) {
			ai->LastRepairBuilding = LuaToNumber(l, j + 1);
		} else {
			LuaError(l, "Unsupported tag: %s" _C_ value);
		}
	}
	return 0;
}
Пример #23
0
/**
**  Define a new upgrade modifier.
**
**  @param l  List of modifiers.
*/
static int CclDefineModifier(lua_State *l)
{
	const char *key;
	const char *value;
	CUpgradeModifier *um;
	int args;
	int j;

	args = lua_gettop(l);

	um = new CUpgradeModifier;

	memset(um->ChangeUpgrades, '?', sizeof(um->ChangeUpgrades));
	memset(um->ApplyTo, '?', sizeof(um->ApplyTo));
	um->Modifier.Variables = new CVariable[UnitTypeVar.NumberVariable];

	um->UpgradeId = UpgradeIdByIdent(LuaToString(l, 1));

	for (j = 1; j < args; ++j) {
		if (!lua_istable(l, j + 1)) {
			LuaError(l, "incorrect argument");
		}
		lua_rawgeti(l, j + 1, 1);
		key = LuaToString(l, -1);
		lua_pop(l, 1);
#if 1 // To be removed. must modify lua file.
		if (!strcmp(key, "attack-range")) {
			key = "AttackRange";
		} else if (!strcmp(key, "sight-range")) {
			key = "SightRange";
		} else if (!strcmp(key, "basic-damage")) {
			key = "BasicDamage";
		} else if (!strcmp(key, "piercing-damage")) {
			key = "PiercingDamage";
		} else if (!strcmp(key, "armor")) {
			key = "Armor";
		} else if (!strcmp(key, "hit-points")) {
			key = "HitPoints";
		}
#endif
		if (!strcmp(key, "regeneration-rate")) {
			lua_rawgeti(l, j + 1, 2);
			um->Modifier.Variables[HP_INDEX].Increase = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else if (!strcmp(key, "cost")) {
			int i;

			if (!lua_istable(l, j + 1) || luaL_getn(l, j + 1) != 2) {
				LuaError(l, "incorrect argument");
			}
			lua_rawgeti(l, j + 1, 1);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			for (i = 0; i < MaxCosts; ++i) {
				if (!strcmp(value, DefaultResourceNames[i])) {
					break;
				}
			}
			if (i == MaxCosts) {
				LuaError(l, "Resource not found: %s" _C_ value);
			}
			lua_rawgeti(l, j + 1, 2);
			um->Modifier.Costs[i] = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else if (!strcmp(key, "allow-unit")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			if (!strncmp(value, "unit-", 5)) {
				lua_rawgeti(l, j + 1, 3);
				um->ChangeUnits[UnitTypeIdByIdent(value)] = LuaToNumber(l, -1);
				lua_pop(l, 1);
			} else {
				LuaError(l, "unit expected");
			}
		} else if (!strcmp(key, "allow")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			if (!strncmp(value, "upgrade-", 8)) {
				lua_rawgeti(l, j + 1, 3);
				um->ChangeUpgrades[UpgradeIdByIdent(value)] = LuaToNumber(l, -1);
				lua_pop(l, 1);
			} else {
				LuaError(l, "upgrade expected");
			}
		} else if (!strcmp(key, "apply-to")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			um->ApplyTo[UnitTypeIdByIdent(value)] = 'X';
		} else if (!strcmp(key, "convert-to")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			um->ConvertTo = UnitTypeByIdent(value);
		} else {
			int index; // variable index;

			index = GetVariableIndex(key);
			if (index != -1) {
				lua_rawgeti(l, j + 1, 2);
				if (lua_istable(l, -1)) {
					DefineVariableField(l, um->Modifier.Variables + index, -1);
				} else if (lua_isnumber(l, -1)) {
					um->Modifier.Variables[index].Enable = 1;
					um->Modifier.Variables[index].Value = LuaToNumber(l, -1);
					um->Modifier.Variables[index].Max = LuaToNumber(l, -1);
				} else {
					LuaError(l, "bad argument type for '%s'\n" _C_ key);
				}
				lua_pop(l, 1);
			} else {
				LuaError(l, "wrong tag: %s" _C_ key);
			}
		}
	}

	UpgradeModifiers[NumUpgradeModifiers++] = um;

	return 0;
}
Пример #24
0
void HandleCommand() {
    char* token;
    int unitID;
    CUnit* unit;
    int actionID;
    int resourceType;
    int x, y;
    char* typeID;
    CUnitType* type;
    int destID;
    CUnit* dest;

    token = NextToken();
    if (!token) return;
    unitID = atoi(token);
    unit = GetUnitByID(unitID);
    if (!unit) {
        SendResponseMessage("Unknown unit.\n", 3);
        return;
    }

    token = NextToken();
    if (!token) return;
    actionID = atoi(token);
    switch (actionID) {
        case 0: // NOOP
            //			SendResponseMessage("OK\n", 3);
            break;

        case 1: // STOP
            SendCommandStopUnit(unit);
            //			SendResponseMessage("OK\n", 3);
            break;

        case 2: // MoveTo <X> <Y>
            token = NextToken();
            if (token == NULL) {
                SendResponseMessage("Bad arguments to Move Action.\n", 3);
                return;
            }
            x = atoi(token);
            token = NextToken();
            if (token == NULL) {
                SendResponseMessage("Bad arguments to Move Action.\n", 3);
                return;
            }
            y = atoi(token);
            SendCommandMove(unit, x, y, 1);
            //			SendResponseMessage("OK\n", 3);
            break;

        case 3: // Build <Type> <X> <Y>
            token = NextToken();
            if (token == NULL) {
                SendResponseMessage("Bad arguments to Build Action.\n", 3);
                return;
            }
            typeID = token;
            type = UnitTypeByIdent(typeID);
            if (type == NULL) {
                SendResponseMessage("Unknown type to build.\n", 3);
                return;
            }
            // If it's a building, train the unit.
            if (unit->Type->Building)
                SendCommandTrainUnit(unit, type, 1);
            else // otherwise, build a building.
            {
                token = NextToken();
                if (token == NULL) {
                    SendResponseMessage("Bad arguments to Build Action.\n", 3);
                    return;
                }
                x = atoi(token);
                token = NextToken();
                if (token == NULL) {
                    SendResponseMessage("Bad arguments to Build Action.\n", 3);
                    return;
                }
                y = atoi(token);
                SendCommandBuildBuilding(unit, x, y, type, 1);
            }
            SendResponseMessage("OK\n", 3);
            break;

        case 4: // Attack <UnitID>
            token = NextToken();
            if (!token) return;
            destID = atoi(token);
            dest = GetUnitByID(destID);
            if (!dest) {
                SendResponseMessage("Unknown unit to attack.\n", 3);
                return;
            }
            SendCommandAttack(unit, 0, 0, dest, 1);
            SendResponseMessage("OK\n", 3);
            break;

        case 5: // Repair <UnitID>
            token = NextToken();
            if (!token) return;
            destID = atoi(token);
            dest = GetUnitByID(destID);
            if (!dest) {
                SendResponseMessage("Unknown unit to repair.\n", 3);
                return;
            }
            SendCommandRepair(unit, 0, 0, dest, 1);
            SendResponseMessage("OK\n", 3);
            break;

        case 6: // Harvest <ResourceType>
            token = NextToken();
            if (!token) return;
            resourceType = atoi(token); // GOLD = 1, WOOD = 2
            FindAndGatherResource(unit, resourceType);
            break;

        case 7: // Return resource
            ReturnResource(unit);
            break;

        case 8: // Harvest unit (gold/oil) <DestUnit>
            token = NextToken();
            if (!token) {
                SendResponseMessage("Invalid harvest argument.\n", 3);
                return;
            }
            destID = atoi(token);
            dest = GetUnitByID(destID);
            if (dest == NoUnitP) {
                SendResponseMessage("Invalid resource unit ID.\n", 3);
                return;
            }
            SendCommandResource(unit, dest, 1);
            SendResponseMessage("OK\n", 3);
            break;

        case 9: // Harvest terrain (wood) <X> <Y>
            token = NextToken();
            if (!token) {
                SendResponseMessage("Invalid harvest argument.\n", 3);
                return;
            }
            x = atoi(token);
            token = NextToken();
            if (!token) {
                SendResponseMessage("Invalid harvest argument.\n", 3);
                return;
            }
            y = atoi(token);
            SendCommandResourceLoc(unit, x, y, 1);
            SendResponseMessage("OK\n", 3);
            break;

        case 10: // Harvest location <ResourceType> <X> <Y>
            token = NextToken();
            if (!token) {
                SendResponseMessage("Invalid harvest argument.\n", 3);
                return;
            }
            resourceType = atoi(token); // GOLD = 1, WOOD = 2
            token = NextToken();
            if (!token) {
                SendResponseMessage("Invalid harvest argument.\n", 3);
                return;
            }
            x = atoi(token);
            token = NextToken();
            if (!token) {
                SendResponseMessage("Invalid harvest argument.\n", 3);
                return;
            }
            y = atoi(token);
            HarvestResAtLoc(resourceType, x, y);
            break;

        default:
            SendResponseMessage("Unknown command.\n", 3);
            return;
    }
}
Пример #25
0
/**
**  Add a new dependency. If already exits append to and rule.
**
**  @param target    Target of the dependency.
**  @param required  Requirement of the dependency.
**  @param count     Amount of the required needed.
**  @param or_flag   Start of or rule.
*/
static void AddDependency(const std::string &target, const std::string required, int count,
	int or_flag)
{
	DependRule rule;
	DependRule *node;
	DependRule *temp;
	int hash;

	//
	//  Setup structure.
	//
	if (!strncmp(target.c_str(), "unit-", 5)) {
		// target string refers to unit-xxx
		rule.Type = DependRuleUnitType;
		rule.Kind.UnitType = UnitTypeByIdent(target);
	} else if (!strncmp(target.c_str(), "upgrade-", 8)) {
		// target string refers to upgrade-XXX
		rule.Type = DependRuleUpgrade;
		rule.Kind.Upgrade = CUpgrade::Get(target);
	} else {
		DebugPrint("dependency target `%s' should be unit-type or upgrade\n" _C_
			target.c_str());
		return;
	}

	hash = (int)((intptr_t)rule.Kind.UnitType % (sizeof(DependHash) / sizeof(*DependHash)));

	//
	//  Find correct hash slot.
	//
	if ((node = DependHash[hash])) {  // find correct entry
		while (node->Type != rule.Type ||
				node->Kind.Upgrade != rule.Kind.Upgrade) {
			if (!node->Next) {  // end of list
				temp = new DependRule;
				temp->Next = NULL;
				temp->Rule = NULL;
				temp->Type = rule.Type;
				temp->Kind = rule.Kind;
				node->Next = temp;
				node = temp;
				break;
			}
			node = node->Next;
		}
	} else {  // create new slow
		node = new DependRule;
		node->Next = NULL;
		node->Rule = NULL;
		node->Type = rule.Type;
		node->Kind = rule.Kind;
		DependHash[hash] = node;
	}

	//
	//  Adjust count.
	//
	if (count < 0 || count > 255) {
		DebugPrint("wrong count `%d' range 0 .. 255\n" _C_ count);
		count = 255;
	}

	temp = new DependRule;
	temp->Rule = NULL;
	temp->Next = NULL;
	temp->Count = count;
	//
	//  Setup structure.
	//
	if (!strncmp(required.c_str(), "unit-", 5)) {
		// required string refers to unit-xxx
		temp->Type = DependRuleUnitType;
		temp->Kind.UnitType = UnitTypeByIdent(required);
	} else if (!strncmp(required.c_str(), "upgrade-", 8)) {
		// required string refers to upgrade-XXX
		temp->Type = DependRuleUpgrade;
		temp->Kind.Upgrade = CUpgrade::Get(required);
	} else {
		DebugPrint("dependency required `%s' should be unit-type or upgrade\n" _C_
			required.c_str());
		delete temp;
		return;
	}

	if (or_flag) {
		// move rule to temp->next
		temp->Next = node->Rule;  // insert rule
		node->Rule = temp;
	} else {
		// move rule to temp->rule
		temp->Rule = node->Rule;  // insert rule

		// also Link temp to old "or" list
		if (node->Rule) {
			temp->Next = node->Rule->Next;
		}

		node->Rule = temp;
	}

#ifdef neverDEBUG
	printf("New rules are :");
	node = node->Rule;
	while (node) {
		temp = node;
		while (temp) {
			printf("temp->Kind.UnitType=%p ", temp->Kind.UnitType);
			temp = temp->Rule;
		}
		node = node->Next;
		printf("\n or ... ");
	}
	printf("\n");
#endif
}
Пример #26
0
/**
**	Have unit of type.
**
**	@param player	Pointer to owning player.
**	@param ident	Identifier of unit-type that should be lookuped.
**	@return		How many exists, false otherwise.
**
**	@note	This function should not be used during run time.
*/
global int HaveUnitTypeByIdent(const Player* player,const char* ident)
{
    return player->UnitTypesCount[UnitTypeByIdent(ident)->Type];
}
Пример #27
0
static int CclDefinePredependency(lua_State *l)
{
	const int args = lua_gettop(l);
	const char *target = LuaToString(l, 1);

	std::vector<const CDependency *> and_dependencies;
	
	//  All or rules.
	bool or_flag = false;
	for (int j = 1; j < args; ++j) {
		if (!lua_istable(l, j + 1)) {
			LuaError(l, "incorrect argument");
		}
		const int subargs = lua_rawlen(l, j + 1);

		std::vector<const CDependency *> dependencies;
	
		for (int k = 0; k < subargs; ++k) {
			const char *required = LuaToString(l, j + 1, k + 1);
			int count = 1;
			if (k + 1 < subargs) {
				lua_rawgeti(l, j + 1, k + 2);
				if (lua_isnumber(l, -1)) {
					count = LuaToNumber(l, -1);
					++k;
				}
				lua_pop(l, 1);
			}
			CDependency *dependency = nullptr;
			
			if (!strncmp(required, "unit-", 5)) {
				const CUnitType *unit_type = UnitTypeByIdent(required);
				if (!unit_type) {
					LuaError(l, "Invalid unit type: \"%s\"" _C_ required);
				}
				dependency = new CUnitTypeDependency(unit_type, count > 0 ? count : 1);
			} else if (!strncmp(required, "upgrade-", 8)) {
				const CUpgrade *upgrade = CUpgrade::Get(required);
				if (!upgrade) {
					LuaError(l, "Invalid upgrade: \"%s\"" _C_ required);
				}
				dependency = new CUpgradeDependency(upgrade);
			} else {
				LuaError(l, "Invalid required type for dependency: \"%s\"" _C_ required);
			}
			
			if (count == 0) {
				dependency = new CNotDependency(dependency);
			}
			
			dependencies.push_back(dependency);
		}
		if (j + 1 < args) {
			++j;
			const char *value = LuaToString(l, j + 1);
			if (strcmp(value, "or")) {
				LuaError(l, "not or symbol: %s" _C_ value);
				return 0;
			}
			or_flag = true;
		}
		
		and_dependencies.push_back(new CAndDependency(dependencies));
		dependencies.clear();
	}
	
	CDependency *dependency = nullptr;
	if (or_flag) {
		dependency = new COrDependency(and_dependencies);
	} else {
		dependency = new CAndDependency(and_dependencies);
	}
	
	if (!strncmp(target, "unit-", 5)) {
		CUnitType *unit_type = UnitTypeByIdent(target);
		if (!unit_type) {
			LuaError(l, "Invalid unit type: \"%s\"" _C_ target);
		}
		unit_type->Predependency = dependency;
	} else if (!strncmp(target, "upgrade-", 8)) {
		CUpgrade *upgrade = CUpgrade::Get(target);
		if (!upgrade) {
			LuaError(l, "Invalid upgrade: \"%s\"" _C_ target);
		}
		upgrade->Predependency = dependency;
	} else {
		LuaError(l, "Invalid dependency target: \"%s\"" _C_ target);
	}
	
	return 0;
}
Пример #28
0
/**
**  Gets the player data.
**
**  @param player  Player number.
**  @param prop    Player's property.
**  @param arg     Additional argument (for resource and unit).
**
**  @return  Returning value (only integer).
*/
int GetPlayerData(const int player, const char *prop, const char *arg)
{
	if (!strcmp(prop, "RaceName")) {
		return Players[player].Race;
	} else if (!strcmp(prop, "Resources")) {
		const int resId = GetResourceIdByName(arg);
		if (resId == -1) {
			fprintf(stderr, "Invalid resource \"%s\"", arg);
			Exit(1);
		}
		return Players[player].Resources[resId] + Players[player].StoredResources[resId];
	} else if (!strcmp(prop, "StoredResources")) {
		const int resId = GetResourceIdByName(arg);
		if (resId == -1) {
			fprintf(stderr, "Invalid resource \"%s\"", arg);
			Exit(1);
		}
		return Players[player].StoredResources[resId];
	} else if (!strcmp(prop, "MaxResources")) {
		const int resId = GetResourceIdByName(arg);
		if (resId == -1) {
			fprintf(stderr, "Invalid resource \"%s\"", arg);
			Exit(1);
		}
		return Players[player].MaxResources[resId];
	} else if (!strcmp(prop, "Incomes")) {
		const int resId = GetResourceIdByName(arg);
		if (resId == -1) {
			fprintf(stderr, "Invalid resource \"%s\"", arg);
			Exit(1);
		}
		return Players[player].Incomes[resId];
	} else if (!strcmp(prop, "UnitTypesCount")) {
		const std::string unit(arg);
		CUnitType *type = UnitTypeByIdent(unit);
		Assert(type);
		return Players[player].UnitTypesCount[type->Slot];
	} else if (!strcmp(prop, "AiEnabled")) {
		return Players[player].AiEnabled;
	} else if (!strcmp(prop, "TotalNumUnits")) {
		return Players[player].GetUnitCount();
	} else if (!strcmp(prop, "NumBuildings")) {
		return Players[player].NumBuildings;
	} else if (!strcmp(prop, "Supply")) {
		return Players[player].Supply;
	} else if (!strcmp(prop, "Demand")) {
		return Players[player].Demand;
	} else if (!strcmp(prop, "UnitLimit")) {
		return Players[player].UnitLimit;
	} else if (!strcmp(prop, "BuildingLimit")) {
		return Players[player].BuildingLimit;
	} else if (!strcmp(prop, "TotalUnitLimit")) {
		return Players[player].TotalUnitLimit;
	} else if (!strcmp(prop, "Score")) {
		return Players[player].Score;
	} else if (!strcmp(prop, "TotalUnits")) {
		return Players[player].TotalUnits;
	} else if (!strcmp(prop, "TotalBuildings")) {
		return Players[player].TotalBuildings;
	} else if (!strcmp(prop, "TotalResources")) {
		const int resId = GetResourceIdByName(arg);
		if (resId == -1) {
			fprintf(stderr, "Invalid resource \"%s\"", arg);
			Exit(1);
		}
		return Players[player].TotalResources[resId];
	} else if (!strcmp(prop, "TotalRazings")) {
		return Players[player].TotalRazings;
	} else if (!strcmp(prop, "TotalKills")) {
		return Players[player].TotalKills;
	} else {
		fprintf(stderr, "Invalid field: %s" _C_ prop);
		Exit(1);
	}
	return 0;
}
Пример #29
0
/**
**  Parse unit
**
**  @param l  Lua state.
**
**  @todo  Verify that vision table is always correct (transporter)
**  @todo (PlaceUnit() and host-info).
*/
static int CclUnit(lua_State *l)
{
	const int slot = LuaToNumber(l, 1);

	if (!lua_istable(l, 2)) {
		LuaError(l, "incorrect argument");
	}

	CUnit *unit = NULL;
	CUnitType *type = NULL;
	CUnitType *seentype = NULL;
	CPlayer *player = NULL;

	// Parse the list:
	const int args = lua_rawlen(l, 2);
	for (int j = 0; j < args; ++j) {
		const char *value = LuaToString(l, 2, j + 1);
		++j;

		if (!strcmp(value, "type")) {
			type = UnitTypeByIdent(LuaToString(l, 2, j + 1));
		} else if (!strcmp(value, "seen-type")) {
			seentype = UnitTypeByIdent(LuaToString(l, 2, j + 1));
		} else if (!strcmp(value, "player")) {
			player = &Players[LuaToNumber(l, 2, j + 1)];

			// During a unit's death animation (when action is "die" but the
			// unit still has its original type, i.e. it's still not a corpse)
			// the unit is already removed from map and from player's
			// unit list (=the unit went through LetUnitDie() which
			// calls RemoveUnit() and UnitLost()).  Such a unit should not
			// be put on player's unit list!  However, this state is not
			// easily detected from this place.  It seems that it is
			// characterized by
			// unit->CurrentAction()==UnitActionDie so we have to wait
			// until we parsed at least Unit::Orders[].
			Assert(type);
			unit = &UnitManager.GetSlotUnit(slot);
			unit->Init(*type);
			unit->Seen.Type = seentype;
			unit->Active = 0;
			unit->Removed = 0;
			Assert(UnitNumber(*unit) == slot);
		} else if (!strcmp(value, "current-sight-range")) {
			unit->CurrentSightRange = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "refs")) {
			unit->Refs = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "host-info")) {
			lua_rawgeti(l, 2, j + 1);
			if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 4) {
				LuaError(l, "incorrect argument");
			}
			Vec2i pos;
			int w;
			int h;

			pos.x = LuaToNumber(l, -1, 1);
			pos.y = LuaToNumber(l, -1, 2);
			w = LuaToNumber(l, -1, 3);
			h = LuaToNumber(l, -1, 4);
			MapSight(*player, pos, w, h, unit->CurrentSightRange, MapMarkTileSight);
			// Detectcloak works in container
			if (unit->Type->DetectCloak) {
				MapSight(*player, pos, w, h, unit->CurrentSightRange, MapMarkTileDetectCloak);
			}
			// Radar(Jammer) not.
			lua_pop(l, 1);
		} else if (!strcmp(value, "tile")) {
			lua_rawgeti(l, 2, j + 1);
			CclGetPos(l, &unit->tilePos.x , &unit->tilePos.y, -1);
			lua_pop(l, 1);
			unit->Offset = Map.getIndex(unit->tilePos);
		} else if (!strcmp(value, "seen-tile")) {
			lua_rawgeti(l, 2, j + 1);
			CclGetPos(l, &unit->Seen.tilePos.x , &unit->Seen.tilePos.y, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "stats")) {
			unit->Stats = &type->Stats[LuaToNumber(l, 2, j + 1)];
		} else if (!strcmp(value, "pixel")) {
			lua_rawgeti(l, 2, j + 1);
			CclGetPos(l, &unit->IX , &unit->IY, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "seen-pixel")) {
			lua_rawgeti(l, 2, j + 1);
			CclGetPos(l, &unit->Seen.IX , &unit->Seen.IY, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "frame")) {
			unit->Frame = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "seen")) {
			unit->Seen.Frame = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "not-seen")) {
			unit->Seen.Frame = UnitNotSeen;
			--j;
		} else if (!strcmp(value, "direction")) {
			unit->Direction = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "damage-type")) {
			unit->DamagedType = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "attacked")) {
			// FIXME : unsigned long should be better handled
			unit->Attacked = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "auto-repair")) {
			unit->AutoRepair = 1;
			--j;
		} else if (!strcmp(value, "burning")) {
			unit->Burning = 1;
			--j;
		} else if (!strcmp(value, "destroyed")) {
			unit->Destroyed = 1;
			--j;
		} else if (!strcmp(value, "removed")) {
			unit->Removed = 1;
			--j;
		} else if (!strcmp(value, "selected")) {
			unit->Selected = 1;
			--j;
		} else if (!strcmp(value, "summoned")) {
			unit->Summoned = 1;
			--j;
		} else if (!strcmp(value, "waiting")) {
			unit->Waiting = 1;
			--j;
		} else if (!strcmp(value, "mine-low")) {
			unit->MineLow = 1;
			--j;
		} else if (!strcmp(value, "rescued-from")) {
			unit->RescuedFrom = &Players[LuaToNumber(l, 2, j + 1)];
		} else if (!strcmp(value, "seen-by-player")) {
			const char *s = LuaToString(l, 2, j + 1);
			unit->Seen.ByPlayer = 0;
			for (int i = 0; i < PlayerMax && *s; ++i, ++s) {
				if (*s == '-' || *s == '_' || *s == ' ') {
					unit->Seen.ByPlayer &= ~(1 << i);
				} else {
					unit->Seen.ByPlayer |= (1 << i);
				}
			}
		} else if (!strcmp(value, "seen-destroyed")) {
			const char *s = LuaToString(l, 2, j + 1);
			unit->Seen.Destroyed = 0;
			for (int i = 0; i < PlayerMax && *s; ++i, ++s) {
				if (*s == '-' || *s == '_' || *s == ' ') {
					unit->Seen.Destroyed &= ~(1 << i);
				} else {
					unit->Seen.Destroyed |= (1 << i);
				}
			}
		} else if (!strcmp(value, "constructed")) {
			unit->Constructed = 1;
			--j;
		} else if (!strcmp(value, "seen-constructed")) {
			unit->Seen.Constructed = 1;
			--j;
		} else if (!strcmp(value, "seen-state")) {
			unit->Seen.State = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "active")) {
			unit->Active = 1;
			--j;
		} else if (!strcmp(value, "ttl")) {
			// FIXME : unsigned long should be better handled
			unit->TTL = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "threshold")) {
			// FIXME : unsigned long should be better handled
			unit->Threshold = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "group-id")) {
			unit->GroupId = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "last-group")) {
			unit->LastGroup = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "resources-held")) {
			unit->ResourcesHeld = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "current-resource")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->CurrentResource = CclGetResourceByName(l);
			lua_pop(l, 1);
		} else if (!strcmp(value, "pathfinder-input")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->pathFinderData->input.Load(l);
			lua_pop(l, 1);
		} else if (!strcmp(value, "pathfinder-output")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->pathFinderData->output.Load(l);
			lua_pop(l, 1);
		} else if (!strcmp(value, "wait")) {
			unit->Wait = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "anim-data")) {
			lua_rawgeti(l, 2, j + 1);
			CAnimations::LoadUnitAnim(l, *unit, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "wait-anim-data")) {
			lua_rawgeti(l, 2, j + 1);
			CAnimations::LoadWaitUnitAnim(l, *unit, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "blink")) {
			unit->Blink = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "moving")) {
			unit->Moving = 1;
			--j;
		} else if (!strcmp(value, "re-cast")) {
			unit->ReCast = 1;
			--j;
		} else if (!strcmp(value, "boarded")) {
			unit->Boarded = 1;
			--j;
		} else if (!strcmp(value, "next-worker")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->NextWorker = CclGetUnitFromRef(l);
			lua_pop(l, 1);
		} else if (!strcmp(value, "resource-workers")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->Resource.Workers = CclGetUnitFromRef(l);
			lua_pop(l, 1);
		} else if (!strcmp(value, "resource-assigned")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->Resource.Assigned = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "resource-active")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			unit->Resource.Active = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else if (!strcmp(value, "units-boarded-count")) {
			unit->BoardCount = LuaToNumber(l, 2, j + 1);
		} else if (!strcmp(value, "units-contained")) {
			int subargs;
			int k;
			lua_rawgeti(l, 2, j + 1);
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			subargs = lua_rawlen(l, -1);
			for (k = 0; k < subargs; ++k) {
				lua_rawgeti(l, -1, k + 1);
				CUnit *u = CclGetUnitFromRef(l);
				lua_pop(l, 1);
				u->AddInContainer(*unit);
			}
			lua_pop(l, 1);
		} else if (!strcmp(value, "orders")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			CclParseOrders(l, *unit);
			lua_pop(l, 1);
			// now we know unit's action so we can assign it to a player
			Assert(player != NULL);
			unit->AssignToPlayer(*player);
			if (unit->CurrentAction() == UnitActionBuilt) {
				DebugPrint("HACK: the building is not ready yet\n");
				// HACK: the building is not ready yet
				unit->Player->UnitTypesCount[type->Slot]--;
				if (unit->Active) {
					unit->Player->UnitTypesAiActiveCount[type->Slot]--;
				}
			}
		} else if (!strcmp(value, "critical-order")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			CclParseOrder(l, *unit , &unit->CriticalOrder);
			lua_pop(l, 1);
		} else if (!strcmp(value, "saved-order")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			CclParseOrder(l, *unit, &unit->SavedOrder);
			lua_pop(l, 1);
		} else if (!strcmp(value, "new-order")) {
			lua_rawgeti(l, 2, j + 1);
			lua_pushvalue(l, -1);
			CclParseOrder(l, *unit, &unit->NewOrder);
			lua_pop(l, 1);
		} else if (!strcmp(value, "goal")) {
			unit->Goal = &UnitManager.GetSlotUnit(LuaToNumber(l, 2, j + 1));
		} else if (!strcmp(value, "auto-cast")) {
			const char *s = LuaToString(l, 2, j + 1);
			Assert(SpellTypeByIdent(s));
			if (!unit->AutoCastSpell) {
				unit->AutoCastSpell = new char[SpellTypeTable.size()];
				memset(unit->AutoCastSpell, 0, SpellTypeTable.size());
			}
			unit->AutoCastSpell[SpellTypeByIdent(s)->Slot] = 1;
		} else if (!strcmp(value, "spell-cooldown")) {
			lua_rawgeti(l, 2, j + 1);
			if (!lua_istable(l, -1) || lua_rawlen(l, -1) != SpellTypeTable.size()) {
				LuaError(l, "incorrect argument");
			}
			if (!unit->SpellCoolDownTimers) {
				unit->SpellCoolDownTimers = new int[SpellTypeTable.size()];
				memset(unit->SpellCoolDownTimers, 0, SpellTypeTable.size() * sizeof(int));
			}
			for (size_t k = 0; k < SpellTypeTable.size(); ++k) {
				unit->SpellCoolDownTimers[k] = LuaToNumber(l, -1, k + 1);
			}
			lua_pop(l, 1);
		} else {
			const int index = UnitTypeVar.VariableNameLookup[value];// User variables
			if (index != -1) { // Valid index
				lua_rawgeti(l, 2, j + 1);
				DefineVariableField(l, unit->Variable + index, -1);
				lua_pop(l, 1);
				continue;
			}
			LuaError(l, "Unit: Unsupported tag: %s" _C_ value);
		}
	}

	// Unit may not have been assigned to a player before now. If not,
	// do so now. It is only assigned earlier if we have orders.
	// for loading of units from a MAP, and not a savegame, we won't
	// have orders for those units.  They should appear here as if
	// they were just created.
	if (!unit->Player) {
		Assert(player);
		unit->AssignToPlayer(*player);
		UpdateForNewUnit(*unit, 0);
	}

	//  Revealers are units that can see while removed
	if (unit->Removed && unit->Type->Revealer) {
		MapMarkUnitSight(*unit);
	}

	// Fix Colors for rescued units.
	if (unit->RescuedFrom) {
		unit->Colors = &unit->RescuedFrom->UnitColors;
	}

	return 0;
}
Пример #30
0
/**
**  Do next replay
*/
static void DoNextReplay()
{
	Assert(ReplayStep != 0);

	NextLogCycle = ReplayStep->GameCycle;

	if (NextLogCycle != GameCycle) {
		return;
	}

	const int unitSlot = ReplayStep->UnitNumber;
	const char *action = ReplayStep->Action.c_str();
	const int flags = ReplayStep->Flush;
	const Vec2i pos(ReplayStep->PosX, ReplayStep->PosY);
	const int arg1 = ReplayStep->PosX;
	const int arg2 = ReplayStep->PosY;
	CUnit *unit = unitSlot != -1 ? &UnitManager.GetSlotUnit(unitSlot) : NULL;
	CUnit *dunit = (ReplayStep->DestUnitNumber != -1 ? &UnitManager.GetSlotUnit(ReplayStep->DestUnitNumber) : NULL);
	const char *val = ReplayStep->Value.c_str();
	const int num = ReplayStep->Num;

	Assert(unitSlot == -1 || ReplayStep->UnitIdent == unit->Type->Ident);

	if (SyncRandSeed != ReplayStep->SyncRandSeed) {
#ifdef DEBUG
		if (!ReplayStep->SyncRandSeed) {
			// Replay without the 'sync info
			ThisPlayer->Notify("%s", _("No sync info for this replay !"));
		} else {
			ThisPlayer->Notify(_("Replay got out of sync (%lu) !"), GameCycle);
			DebugPrint("OUT OF SYNC %u != %u\n" _C_ SyncRandSeed _C_ ReplayStep->SyncRandSeed);
			DebugPrint("OUT OF SYNC GameCycle %lu \n" _C_ GameCycle);
			Assert(0);
			// ReplayStep = 0;
			// NextLogCycle = ~0UL;
			// return;
		}
#else
		ThisPlayer->Notify("%s", _("Replay got out of sync !"));
		ReplayStep = 0;
		NextLogCycle = ~0UL;
		return;
#endif
	}

	if (!strcmp(action, "stop")) {
		SendCommandStopUnit(*unit);
	} else if (!strcmp(action, "stand-ground")) {
		SendCommandStandGround(*unit, flags);
	} else if (!strcmp(action, "defend")) {
		SendCommandDefend(*unit, *dunit, flags);
	} else if (!strcmp(action, "follow")) {
		SendCommandFollow(*unit, *dunit, flags);
	} else if (!strcmp(action, "move")) {
		SendCommandMove(*unit, pos, flags);
	//Wyrmgus start
	} else if (!strcmp(action, "pick-up")) {
		SendCommandPickUp(*unit, *dunit, flags);
	//Wyrmgus end
	} else if (!strcmp(action, "repair")) {
		SendCommandRepair(*unit, pos, dunit, flags);
	} else if (!strcmp(action, "auto-repair")) {
		SendCommandAutoRepair(*unit, arg1);
	} else if (!strcmp(action, "attack")) {
		SendCommandAttack(*unit, pos, dunit, flags);
	} else if (!strcmp(action, "attack-ground")) {
		SendCommandAttackGround(*unit, pos, flags);
	//Wyrmgus start
	} else if (!strcmp(action, "use")) {
		SendCommandUse(*unit, *dunit, flags);
	} else if (!strcmp(action, "trade")) {
		SendCommandTrade(*unit, *dunit, flags);
	//Wyrmgus end
	} else if (!strcmp(action, "patrol")) {
		SendCommandPatrol(*unit, pos, flags);
	} else if (!strcmp(action, "board")) {
		SendCommandBoard(*unit, *dunit, flags);
	} else if (!strcmp(action, "unload")) {
		SendCommandUnload(*unit, pos, dunit, flags);
	} else if (!strcmp(action, "build")) {
		SendCommandBuildBuilding(*unit, pos, *UnitTypeByIdent(val), flags);
	} else if (!strcmp(action, "dismiss")) {
		SendCommandDismiss(*unit);
	} else if (!strcmp(action, "resource-loc")) {
		SendCommandResourceLoc(*unit, pos, flags);
	} else if (!strcmp(action, "resource")) {
		SendCommandResource(*unit, *dunit, flags);
	} else if (!strcmp(action, "return")) {
		SendCommandReturnGoods(*unit, dunit, flags);
	} else if (!strcmp(action, "train")) {
		//Wyrmgus start
//		SendCommandTrainUnit(*unit, *UnitTypeByIdent(val), flags);
		SendCommandTrainUnit(*unit, *UnitTypeByIdent(val), num, flags);
		//Wyrmgus end
	} else if (!strcmp(action, "cancel-train")) {
		SendCommandCancelTraining(*unit, num, (val && *val) ? UnitTypeByIdent(val) : NULL);
	} else if (!strcmp(action, "upgrade-to")) {
		SendCommandUpgradeTo(*unit, *UnitTypeByIdent(val), flags);
	} else if (!strcmp(action, "cancel-upgrade-to")) {
		SendCommandCancelUpgradeTo(*unit);
	//Wyrmgus start
	} else if (!strcmp(action, "transform-into")) {
		SendCommandTransformInto(*unit, *UnitTypeByIdent(val), flags);
	//Wyrmgus end
	} else if (!strcmp(action, "research")) {
		//Wyrmgus start
//		SendCommandResearch(*unit, *CUpgrade::Get(val), flags);
		SendCommandResearch(*unit, *CUpgrade::Get(val), num, flags);
		//Wyrmgus end
	} else if (!strcmp(action, "cancel-research")) {
		SendCommandCancelResearch(*unit);
	//Wyrmgus start
	} else if (!strcmp(action, "learn-ability")) {
		SendCommandLearnAbility(*unit, *CUpgrade::Get(val));
	//Wyrmgus end
	} else if (!strcmp(action, "spell-cast")) {
		SendCommandSpellCast(*unit, pos, dunit, num, flags);
	} else if (!strcmp(action, "auto-spell-cast")) {
		SendCommandAutoSpellCast(*unit, num, arg1);
	//Wyrmgus start
	} else if (!strcmp(action, "rally-point")) {
		SendCommandRallyPoint(*unit, pos);
	} else if (!strcmp(action, "quest")) {
		SendCommandQuest(*unit, GetQuest(val));
	} else if (!strcmp(action, "buy")) {
		SendCommandBuy(*unit, dunit, num);
	} else if (!strcmp(action, "produce-resource")) {
		SendCommandProduceResource(*unit, num);
	} else if (!strcmp(action, "sell-resource")) {
		SendCommandSellResource(*unit, arg1, num);
	} else if (!strcmp(action, "buy-resource")) {
		SendCommandBuyResource(*unit, arg1, num);
	//Wyrmgus end
	} else if (!strcmp(action, "diplomacy")) {
		int state;
		if (!strcmp(val, "neutral")) {
			state = DiplomacyNeutral;
		} else if (!strcmp(val, "allied")) {
			state = DiplomacyAllied;
		} else if (!strcmp(val, "enemy")) {
			state = DiplomacyEnemy;
		//Wyrmgus start
		} else if (!strcmp(val, "overlord")) {
			state = DiplomacyOverlord;
		} else if (!strcmp(val, "vassal")) {
			state = DiplomacyVassal;
		//Wyrmgus end
		} else if (!strcmp(val, "crazy")) {
			state = DiplomacyCrazy;
		} else {
			DebugPrint("Invalid diplomacy command: %s" _C_ val);
			state = -1;
		}
		SendCommandDiplomacy(arg1, state, arg2);
	} else if (!strcmp(action, "shared-vision")) {
		bool state;
		state = atoi(val) ? true : false;
		SendCommandSharedVision(arg1, state, arg2);
	} else if (!strcmp(action, "input")) {
		if (val[0] == '-') {
			CclCommand(val + 1, false);
		} else {
			HandleCheats(val);
		}
	} else if (!strcmp(action, "chat")) {
		SetMessage("%s", val);
		PlayGameSound(GameSounds.ChatMessage.Sound, MaxSampleVolume);
	} else if (!strcmp(action, "quit")) {
		CommandQuit(arg1);
	} else {
		DebugPrint("Invalid action: %s" _C_ action);
	}

	ReplayStep = ReplayStep->Next;
	NextLogCycle = ReplayStep ? (unsigned)ReplayStep->GameCycle : ~0UL;
}