/** ** 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); } } }
/** ** Initialize missile type. */ void MissileType::Init(void) { // // Resolve impact missiles and sounds. // if (!this->FiredSound.Name.empty()) { this->FiredSound.Sound = SoundForName(this->FiredSound.Name); } if (!this->ImpactSound.Name.empty()) { this->ImpactSound.Sound = SoundForName(this->ImpactSound.Name); } this->ImpactMissile = MissileTypeByIdent(this->ImpactName); this->SmokeMissile = MissileTypeByIdent(this->SmokeName); }
/* virtual */ void Spell_AreaBombardment::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, "fields")) { this->Fields = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "shards")) { this->Shards = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "damage")) { this->Damage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "start-offset-x")) { this->StartOffsetX = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "start-offset-y")) { this->StartOffsetY = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "missile")) { value = LuaToString(l, -1, j + 1); this->Missile = MissileTypeByIdent(value); if (this->Missile == NULL) { DebugPrint("in area-bombardement : missile %s does not exist\n" _C_ value); } } else { LuaError(l, "Unsupported area-bombardment tag: %s" _C_ value); } } // Now, checking value. if (this->Missile == NULL) { LuaError(l, "Use a missile for area-bombardment (with missile)"); } }
/** ** Define burning building missiles. ** ** @param l Lua state. */ static int CclDefineBurningBuilding(lua_State *l) { for (std::vector<BurningBuildingFrame *>::iterator i = BurningBuildingFrames.begin(); i != BurningBuildingFrames.end(); ++i) { delete *i; } BurningBuildingFrames.clear(); const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } BurningBuildingFrame *ptr = new BurningBuildingFrame; const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { const char *value = LuaToString(l, j + 1, k + 1); ++k; if (!strcmp(value, "percent")) { ptr->Percent = LuaToNumber(l, j + 1, k + 1); } else if (!strcmp(value, "missile")) { ptr->Missile = MissileTypeByIdent(LuaToString(l, j + 1, k + 1)); } } BurningBuildingFrames.insert(BurningBuildingFrames.begin(), ptr); } return 0; }
/** ** Create a missile on the map ** ** @param l Lua state. ** */ static int CclCreateMissile(lua_State *l) { LuaCheckArgs(l, 6); const std::string name = LuaToString(l, 1); const MissileType *mtype = MissileTypeByIdent(name); if (!mtype) { LuaError(l, "Bad missile"); } PixelPos startpos, endpos; if (!lua_istable(l, 2) || lua_rawlen(l, 2) != 2) { LuaError(l, "incorrect argument !!"); } lua_rawgeti(l, 2, 1); startpos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 2, 2); startpos.y = LuaToNumber(l, -1); lua_pop(l, 1); if (!lua_istable(l, 3) || lua_rawlen(l, 3) != 2) { LuaError(l, "incorrect argument !!"); } lua_rawgeti(l, 3, 1); endpos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 3, 2); endpos.y = LuaToNumber(l, -1); lua_pop(l, 1); const int sourceUnitId = LuaToNumber(l, 4); const int destUnitId = LuaToNumber(l, 5); const bool dealDamage = LuaToBoolean(l, 6); CUnit *sourceUnit = sourceUnitId != -1 ? &UnitManager.GetSlotUnit(sourceUnitId) : NULL; CUnit *destUnit = destUnitId != -1 ? &UnitManager.GetSlotUnit(destUnitId) : NULL; if (sourceUnit != NULL) { startpos += sourceUnit->GetMapPixelPosTopLeft(); } if (destUnit != NULL) { endpos += destUnit->GetMapPixelPosTopLeft(); } Missile *missile = MakeMissile(*mtype, startpos, endpos); if (!missile) { return 0; } if (dealDamage) { missile->SourceUnit = sourceUnit; } missile->TargetUnit = destUnit; return 0; }
/** ** Create a missile on the map ** ** @param l Lua state. ** */ static int CclCreateMissile(lua_State *l) { const int arg = lua_gettop(l); if (arg < 6 || arg > 7) { LuaError(l, "incorrect argument"); } const std::string name = LuaToString(l, 1); const MissileType *mtype = MissileTypeByIdent(name); if (!mtype) { LuaError(l, "Bad missile"); } PixelPos startpos, endpos; CclGetPos(l, &startpos.x, &startpos.y, 2); CclGetPos(l, &endpos.x, &endpos.y, 3); const int sourceUnitId = LuaToNumber(l, 4); const int destUnitId = LuaToNumber(l, 5); const bool dealDamage = LuaToBoolean(l, 6); const bool mapRelative = arg == 7 ? LuaToBoolean(l, 7) : false; CUnit *sourceUnit = sourceUnitId != -1 ? &UnitManager.GetSlotUnit(sourceUnitId) : nullptr; CUnit *destUnit = destUnitId != -1 ? &UnitManager.GetSlotUnit(destUnitId) : nullptr; if (mapRelative == false) { if (sourceUnit != nullptr) { startpos += sourceUnit->GetMapPixelPosTopLeft(); } if (destUnit != nullptr) { endpos += destUnit->GetMapPixelPosTopLeft(); } } //Wyrmgus start // Missile *missile = MakeMissile(*mtype, startpos, endpos); Missile *missile = MakeMissile(*mtype, startpos, endpos, 0); //Wyrmgus end if (!missile) { return 0; } if (dealDamage) { missile->SourceUnit = sourceUnit; } missile->TargetUnit = destUnit; return 0; }
/** ** Parse missile-type. ** ** @param l Lua state. */ static int CclDefineMissileType(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument"); } // Slot identifier const char *str = LuaToString(l, 1); MissileType *mtype = MissileTypeByIdent(str); if (mtype) { DebugPrint("Redefining missile-type '%s'\n" _C_ str); } else { mtype = NewMissileTypeSlot(str); } mtype->Load(l); return 0; }
/** ** Create a missile. ** ** @param l Lua state. */ static int CclMissile(lua_State *l) { MissileType *type = nullptr; PixelPos position(-1, -1); PixelPos destination(-1, -1); PixelPos source(-1, -1); int z = 0; Missile *missile = nullptr; DebugPrint("FIXME: not finished\n"); const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; if (!strcmp(value, "type")) { type = MissileTypeByIdent(LuaToString(l, j + 1)); } else if (!strcmp(value, "pos")) { CclGetPos(l, &position.x, &position.y, j + 1); } else if (!strcmp(value, "origin-pos")) { CclGetPos(l, &source.x, &source.y, j + 1); } else if (!strcmp(value, "goal")) { CclGetPos(l, &destination.x, &destination.y, j + 1); //Wyrmgus start } else if (!strcmp(value, "map-layer")) { z = LuaToNumber(l, j + 1); //Wyrmgus end } else if (!strcmp(value, "local")) { Assert(type); //Wyrmgus start // missile = MakeLocalMissile(*type, position, destination); missile = MakeLocalMissile(*type, position, destination, z); //Wyrmgus end missile->Local = 1; --j; } else if (!strcmp(value, "global")) { Assert(type); //Wyrmgus start // missile = MakeMissile(*type, position, destination); missile = MakeMissile(*type, position, destination, z); //Wyrmgus end missile->position = position; missile->source = source; missile->destination = destination; //Wyrmgus start missile->MapLayer = z; //Wyrmgus end missile->Local = 0; --j; } else if (!strcmp(value, "frame")) { Assert(missile); missile->SpriteFrame = LuaToNumber(l, j + 1); } else if (!strcmp(value, "state")) { Assert(missile); missile->State = LuaToNumber(l, j + 1); } else if (!strcmp(value, "anim-wait")) { Assert(missile); missile->AnimWait = LuaToNumber(l, j + 1); } else if (!strcmp(value, "wait")) { Assert(missile); missile->Wait = LuaToNumber(l, j + 1); } else if (!strcmp(value, "delay")) { Assert(missile); missile->Delay = LuaToNumber(l, j + 1); } else if (!strcmp(value, "source")) { Assert(missile); lua_pushvalue(l, j + 1); missile->SourceUnit = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "target")) { Assert(missile); lua_pushvalue(l, j + 1); missile->TargetUnit = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "damage")) { Assert(missile); missile->Damage = LuaToNumber(l, j + 1); } else if (!strcmp(value, "lightning-damage")) { Assert(missile); missile->LightningDamage = LuaToNumber(l, j + 1); } else if (!strcmp(value, "ttl")) { Assert(missile); missile->TTL = LuaToNumber(l, j + 1); } else if (!strcmp(value, "hidden")) { Assert(missile); missile->Hidden = 1; --j; } else if (!strcmp(value, "step")) { Assert(missile); if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 2) { LuaError(l, "incorrect argument"); } missile->CurrentStep = LuaToNumber(l, j + 1, 1); missile->TotalStep = LuaToNumber(l, j + 1, 2); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } // we need to reinitialize position parameters - that's because of // the way InitMissile() (called from MakeLocalMissile()) computes // them - it works for creating a missile during a game but breaks // loading the missile from a file. missile->position = position; missile->source = source; missile->destination = destination; missile->MapLayer = z; return 0; }
/* virtual */ void CAnimation_SpawnMissile::Action(CUnit &unit, int &/*move*/, int /*scale*/) const { Assert(unit.Anim.Anim == this); const int startx = ParseAnimInt(&unit, this->startXStr.c_str()); const int starty = ParseAnimInt(&unit, this->startYStr.c_str()); const int destx = ParseAnimInt(&unit, this->destXStr.c_str()); const int desty = ParseAnimInt(&unit, this->destYStr.c_str()); const int flags = ParseAnimFlags(unit, this->flagsStr.c_str()); const int offsetnum = ParseAnimInt(&unit, this->offsetNumStr.c_str()); const CUnit *goal = flags & ANIM_SM_RELTARGET ? unit.CurrentOrder()->GetGoal() : &unit; const int dir = ((goal->Direction + NextDirection / 2) & 0xFF) / NextDirection; const PixelPos moff = goal->Type->MissileOffsets[dir][!offsetnum ? 0 : offsetnum - 1]; PixelPos start; PixelPos dest; MissileType *mtype = MissileTypeByIdent(this->missileTypeStr); if (mtype == NULL) { return; } if (!goal || goal->Destroyed) { return; } if ((flags & ANIM_SM_PIXEL)) { start.x = goal->tilePos.x * PixelTileSize.x + goal->IX + moff.x + startx; start.y = goal->tilePos.y * PixelTileSize.y + goal->IY + moff.y + starty; } else { start.x = (goal->tilePos.x + startx) * PixelTileSize.x + PixelTileSize.x / 2 + moff.x; start.y = (goal->tilePos.y + starty) * PixelTileSize.y + PixelTileSize.y / 2 + moff.y; } if ((flags & ANIM_SM_TOTARGET)) { CUnit *target = goal->CurrentOrder()->GetGoal(); if (!target || target->Destroyed) { Assert(!mtype->AlwaysFire || mtype->Range); if (!target && mtype->AlwaysFire == false) { return; } } if (!target) { if (goal->CurrentAction() == UnitActionAttack || goal->CurrentAction() == UnitActionAttackGround) { COrder_Attack &order = *static_cast<COrder_Attack *>(goal->CurrentOrder()); dest = Map.TilePosToMapPixelPos_Center(order.GetGoalPos()); } else if (goal->CurrentAction() == UnitActionSpellCast) { COrder_SpellCast &order = *static_cast<COrder_SpellCast *>(goal->CurrentOrder()); dest = Map.TilePosToMapPixelPos_Center(order.GetGoalPos()); } if (flags & ANIM_SM_PIXEL) { dest.x += destx; dest.y += desty; } else { dest.x += destx * PixelTileSize.x; dest.y += desty * PixelTileSize.y; } } else if (flags & ANIM_SM_PIXEL) { dest.x = target->GetMapPixelPosCenter().x + destx; dest.y = target->GetMapPixelPosCenter().y + desty; } else { dest.x = (target->tilePos.x + destx) * PixelTileSize.x; dest.y = (target->tilePos.y + desty) * PixelTileSize.y; dest += target->Type->GetPixelSize() / 2; } } else { if ((flags & ANIM_SM_PIXEL)) { dest.x = goal->GetMapPixelPosCenter().x + destx; dest.y = goal->GetMapPixelPosCenter().y + desty; } else { dest.x = (goal->tilePos.x + destx) * PixelTileSize.x; dest.y = (goal->tilePos.y + desty) * PixelTileSize.y; dest += goal->Type->GetPixelSize() / 2; } } Vec2i destTilePos = Map.MapPixelPosToTilePos(dest); const int dist = goal->MapDistanceTo(destTilePos); if ((flags & ANIM_SM_RANGED) && !(flags & ANIM_SM_PIXEL) && dist > goal->Stats->Variables[ATTACKRANGE_INDEX].Max && dist < goal->Type->MinAttackRange) { } else { Missile *missile = MakeMissile(*mtype, start, dest); if (flags & ANIM_SM_SETDIRECTION) { PixelPos posd; posd.x = Heading2X[goal->Direction / NextDirection]; posd.y = Heading2Y[goal->Direction / NextDirection]; missile->MissileNewHeadingFromXY(posd); } if (flags & ANIM_SM_DAMAGE) { missile->SourceUnit = &unit; } if (flags & ANIM_SM_TOTARGET) { missile->TargetUnit = goal->CurrentOrder()->GetGoal(); } } }
/** ** Parse the action for spell. ** ** @param l Lua state. */ static SpellActionType *CclSpellAction(lua_State *l) { const char *value; int args; int j; if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } args = lua_objlen(l, -1); j = 0; lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "spawn-missile")) { SpawnMissile *spellaction = new SpawnMissile; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "damage")) { lua_rawgeti(l, -1, j + 1); spellaction->Damage = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "delay")) { lua_rawgeti(l, -1, j + 1); spellaction->Delay = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "ttl")) { lua_rawgeti(l, -1, j + 1); spellaction->TTL = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "start-point")) { lua_rawgeti(l, -1, j + 1); CclSpellMissileLocation(l, &spellaction->StartPoint); lua_pop(l, 1); } else if (!strcmp(value, "end-point")) { lua_rawgeti(l, -1, j + 1); CclSpellMissileLocation(l, &spellaction->EndPoint); lua_pop(l, 1); } else if (!strcmp(value, "missile")) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); spellaction->Missile = MissileTypeByIdent(value); if (spellaction->Missile == NULL) { DebugPrint("in spawn-missile : missile %s does not exist\n" _C_ value); } lua_pop(l, 1); } else { LuaError(l, "Unsupported spawn-missile tag: %s" _C_ value); } } // Now, checking value. if (spellaction->Missile == NULL) { LuaError(l, "Use a missile for spawn-missile (with missile)"); } return spellaction; } else if (!strcmp(value, "area-adjust-vitals")) { AreaAdjustVitals *spellaction = new AreaAdjustVitals; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "hit-points")) { lua_rawgeti(l, -1, j + 1); spellaction->HP = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "mana-points")) { lua_rawgeti(l, -1, j + 1); spellaction->Mana = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "Unsupported area-adjust-vitals tag: %s" _C_ value); } } return spellaction; } else if (!strcmp(value, "area-bombardment")) { AreaBombardment *spellaction = new AreaBombardment; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "fields")) { lua_rawgeti(l, -1, j + 1); spellaction->Fields = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "shards")) { lua_rawgeti(l, -1, j + 1); spellaction->Shards = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "damage")) { lua_rawgeti(l, -1, j + 1); spellaction->Damage = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "start-offset-x")) { lua_rawgeti(l, -1, j + 1); spellaction->StartOffsetX = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "start-offset-y")) { lua_rawgeti(l, -1, j + 1); spellaction->StartOffsetY = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "missile")) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); spellaction->Missile = MissileTypeByIdent(value); if (spellaction->Missile == NULL) { DebugPrint("in area-bombardement : missile %s does not exist\n" _C_ value); } lua_pop(l, 1); } else { LuaError(l, "Unsupported area-bombardment tag: %s" _C_ value); } } // Now, checking value. if (spellaction->Missile == NULL) { LuaError(l, "Use a missile for area-bombardment (with missile)"); } return spellaction; } else if (!strcmp(value, "demolish")) { Demolish *spellaction = new Demolish; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "range")) { lua_rawgeti(l, -1, j + 1); spellaction->Range = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "damage")) { lua_rawgeti(l, -1, j + 1); spellaction->Damage = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "Unsupported demolish tag: %s" _C_ value); } } return spellaction; } else if (!strcmp(value, "adjust-variable")) { AdjustVariable *spellaction = new AdjustVariable; lua_rawgeti(l, -1, j + 1); if (!lua_istable(l, -1)) { LuaError(l, "Table expected for adjust-variable."); } spellaction->Var = new SpellActionTypeAdjustVariable[UnitTypeVar.GetNumberVariable()]; for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) { const char *const name = LuaToString(l, -2); int i = UnitTypeVar.VariableNameLookup[name]; if (i == -1) { LuaError(l, "in adjust-variable : Bad variable index : '%s'" _C_ LuaToString(l, -2)); } if (lua_isnumber(l, -1)) { spellaction->Var[i].Enable = (LuaToNumber(l, -1) != 0); spellaction->Var[i].ModifEnable = 1; spellaction->Var[i].Value = LuaToNumber(l, -1); spellaction->Var[i].ModifValue = 1; spellaction->Var[i].Max = LuaToNumber(l, -1); spellaction->Var[i].ModifMax = 1; } else if (lua_istable(l, -1)) { for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) { const char *const key = LuaToString(l, -2); if (!strcmp(key, "Enable")) { spellaction->Var[i].Enable = LuaToBoolean(l, -1); spellaction->Var[i].ModifEnable = 1; } else if (!strcmp(key, "Value")) { spellaction->Var[i].Value = LuaToNumber(l, -1); spellaction->Var[i].ModifValue = 1; } else if (!strcmp(key, "Max")) { spellaction->Var[i].Max = LuaToNumber(l, -1); spellaction->Var[i].ModifMax = 1; } else if (!strcmp(key, "Increase")) { spellaction->Var[i].Increase = LuaToNumber(l, -1); spellaction->Var[i].ModifIncrease = 1; } else if (!strcmp(key, "InvertEnable")) { spellaction->Var[i].InvertEnable = LuaToBoolean(l, -1); } else if (!strcmp(key, "AddValue")) { spellaction->Var[i].AddValue = LuaToNumber(l, -1); } else if (!strcmp(key, "AddMax")) { spellaction->Var[i].AddMax = LuaToNumber(l, -1); } else if (!strcmp(key, "AddIncrease")) { spellaction->Var[i].AddIncrease = LuaToNumber(l, -1); } else if (!strcmp(key, "IncreaseTime")) { spellaction->Var[i].IncreaseTime = LuaToNumber(l, -1); } else if (!strcmp(key, "TargetIsCaster")) { value = LuaToString(l, -1); if (!strcmp(value, "caster")) { spellaction->Var[i].TargetIsCaster = 1; } else if (!strcmp(value, "target")) { spellaction->Var[i].TargetIsCaster = 0; } else { // Error LuaError(l, "key '%s' not valid for TargetIsCaster in adjustvariable" _C_ value); } } else { // Error LuaError(l, "key '%s' not valid for adjustvariable" _C_ key); } } } else { LuaError(l, "in adjust-variable : Bad variable value"); } } lua_pop(l, 1); // pop table return spellaction; } else if (!strcmp(value, "summon")) { Summon *spellaction = new Summon; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "unit-type")) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); spellaction->UnitType = UnitTypeByIdent(value); if (!spellaction->UnitType) { spellaction->UnitType = 0; DebugPrint("unit type \"%s\" not found for summon spell.\n" _C_ value); } } else if (!strcmp(value, "time-to-live")) { lua_rawgeti(l, -1, j + 1); spellaction->TTL = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "require-corpse")) { spellaction->RequireCorpse = 1; --j; } else { LuaError(l, "Unsupported summon tag: %s" _C_ value); } } // Now, checking value. if (spellaction->UnitType == NULL) { LuaError(l, "Use a unittype for summon (with unit-type)"); } return spellaction; } else if (!strcmp(value, "spawn-portal")) { SpawnPortal *spellaction = new SpawnPortal; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); 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); spellaction->PortalType = UnitTypeByIdent(value); if (!spellaction->PortalType) { spellaction->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 (spellaction->PortalType == NULL) { LuaError(l, "Use a unittype for spawn-portal (with portal-type)"); } return spellaction; } else if (!strcmp(value, "capture")) { Capture *spellaction = new Capture; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "sacrifice")) { spellaction->SacrificeEnable = 1; } else if (!strcmp(value, "damage")) { lua_rawgeti(l, -1, j + 1); spellaction->Damage = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "percent")) { lua_rawgeti(l, -1, j + 1); spellaction->DamagePercent = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "Unsupported Capture tag: %s" _C_ value); } } return spellaction; } else if (!strcmp(value, "polymorph")) { Polymorph *spellaction = new Polymorph; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); 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); spellaction->NewForm = UnitTypeByIdent(value); if (!spellaction->NewForm) { spellaction->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")) { spellaction->PlayerNeutral = 1; --j; } else { LuaError(l, "Unsupported polymorph tag: %s" _C_ value); } } // Now, checking value. if (spellaction->NewForm == NULL) { LuaError(l, "Use a unittype for polymorph (with new-form)"); } return spellaction; } else if (!strcmp(value, "adjust-vitals")) { AdjustVitals *spellaction = new AdjustVitals; for (; j < args; ++j) { lua_rawgeti(l, -1, j + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++j; if (!strcmp(value, "hit-points")) { lua_rawgeti(l, -1, j + 1); spellaction->HP = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "mana-points")) { lua_rawgeti(l, -1, j + 1); spellaction->Mana = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "max-multi-cast")) { lua_rawgeti(l, -1, j + 1); spellaction->MaxMultiCast = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "Unsupported adjust-vitals tag: %s" _C_ value); } } return spellaction; } else { LuaError(l, "Unsupported action type: %s" _C_ value); } return NULL; }