コード例 #1
0
ファイル: unittype.cpp プロジェクト: infsega/boswars-playbook
/**
** 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
ファイル: missile.cpp プロジェクト: OneSleepyDev/boswars_osd
/**
**  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);
}
コード例 #3
0
/* 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)");
	}
}
コード例 #4
0
ファイル: script_missile.cpp プロジェクト: Andrettin/Wyrmgus
/**
**  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;
}
コード例 #5
0
ファイル: script_missile.cpp プロジェクト: ajaykon/Stratagus
/**
**  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;
}
コード例 #6
0
ファイル: script_missile.cpp プロジェクト: Andrettin/Wyrmgus
/**
**  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;
}
コード例 #7
0
ファイル: script_missile.cpp プロジェクト: Andrettin/Wyrmgus
/**
**  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;
}
コード例 #8
0
ファイル: script_missile.cpp プロジェクト: Andrettin/Wyrmgus
/**
**  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;
}
コード例 #9
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();
		}
	}
}
コード例 #10
0
/**
**  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;
}