From 9c7004c8cc4e8748ba35adbb29f9f659806efca7 Mon Sep 17 00:00:00 2001 From: cybermind <iddqd_mail@mail.ru> Date: Tue, 30 Apr 2013 19:34:46 +0600 Subject: [PATCH] [*] Spawn-portal spell improvement --- src/action/action_follow.cpp | 62 ++++++++++++++------------- src/include/spell/spell_spawnportal.h | 4 +- src/spell/spell_spawnportal.cpp | 11 ++++- src/ui/mouse.cpp | 6 +-- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/action/action_follow.cpp b/src/action/action_follow.cpp index c80340b0b..adc9227cf 100644 --- a/src/action/action_follow.cpp +++ b/src/action/action_follow.cpp @@ -203,41 +203,43 @@ enum { } // Handle Teleporter Units // FIXME: BAD HACK - if (goal->Type->Teleporter && goal->Goal && unit.MapDistanceTo(*goal) <= 1) { - // Teleport the unit - unit.Remove(NULL); - unit.tilePos = goal->Goal->tilePos; - DropOutOnSide(unit, unit.Direction, NULL); + // goal shouldn't be busy and portal should be alive + if (goal->Type->Teleporter && goal->IsIdle() && goal->Goal + && goal->Goal->IsAlive() && unit.MapDistanceTo(*goal) <= 1) { + // Teleport the unit + unit.Remove(NULL); + unit.tilePos = goal->Goal->tilePos; + DropOutOnSide(unit, unit.Direction, NULL); #if 0 - // FIXME: SoundForName() should be called once - PlayGameSound(SoundForName("invisibility"), MaxSampleVolume); - // FIXME: MissileTypeByIdent() should be called once - MakeMissile(MissileTypeByIdent("missile-normal-spell"), - unit.GetMapPixelPosCenter(), - unit.GetMapPixelPosCenter()); + // FIXME: SoundForName() should be called once + PlayGameSound(SoundForName("invisibility"), MaxSampleVolume); + // FIXME: MissileTypeByIdent() should be called once + MakeMissile(MissileTypeByIdent("missile-normal-spell"), + unit.GetMapPixelPosCenter(), + unit.GetMapPixelPosCenter()); #endif - // FIXME: we must check if the units supports the new order. - CUnit &dest = *goal->Goal; + // FIXME: we must check if the units supports the new order. + CUnit &dest = *goal->Goal; - if (dest.NewOrder == NULL - || (dest.NewOrder->Action == UnitActionResource && !unit.Type->Harvester) - || (dest.NewOrder->Action == UnitActionAttack && !unit.Type->CanAttack) - || (dest.NewOrder->Action == UnitActionBoard && unit.Type->UnitType != UnitTypeLand)) { - this->Finished = true; - return ; - } else { - if (dest.NewOrder->HasGoal()) { - if (dest.NewOrder->GetGoal()->Destroyed) { - delete dest.NewOrder; - dest.NewOrder = NULL; - this->Finished = true; - return ; + if (dest.NewOrder == NULL + || (dest.NewOrder->Action == UnitActionResource && !unit.Type->Harvester) + || (dest.NewOrder->Action == UnitActionAttack && !unit.Type->CanAttack) + || (dest.NewOrder->Action == UnitActionBoard && unit.Type->UnitType != UnitTypeLand)) { + this->Finished = true; + return ; + } else { + if (dest.NewOrder->HasGoal()) { + if (dest.NewOrder->GetGoal()->Destroyed) { + delete dest.NewOrder; + dest.NewOrder = NULL; + this->Finished = true; + return ; + } } + unit.Orders.insert(unit.Orders.begin() + 1, dest.NewOrder->Clone()); + this->Finished = true; + return ; } - unit.Orders.insert(unit.Orders.begin() + 1, dest.NewOrder->Clone()); - this->Finished = true; - return ; - } } this->goalPos = goal->tilePos; this->State = State_TargetReached; diff --git a/src/include/spell/spell_spawnportal.h b/src/include/spell/spell_spawnportal.h index 0c781560e..39ebd42db 100644 --- a/src/include/spell/spell_spawnportal.h +++ b/src/include/spell/spell_spawnportal.h @@ -41,13 +41,15 @@ class Spell_SpawnPortal : public SpellActionType { public: - Spell_SpawnPortal() : PortalType(0) {}; + Spell_SpawnPortal() : PortalType(0), TTL(0), CurrentPlayer(false) {}; virtual int Cast(CUnit &caster, const SpellType &spell, CUnit *target, const Vec2i &goalPos); virtual void Parse(lua_State *l, int startIndex, int endIndex); private: CUnitType *PortalType; /// The unit type spawned + int TTL; /// Time to live for summoned portal. 0 means infinite + bool CurrentPlayer; /// If true, summon portal for caster's player rather than neutral }; diff --git a/src/spell/spell_spawnportal.cpp b/src/spell/spell_spawnportal.cpp index 59fa020c4..b444dacf7 100644 --- a/src/spell/spell_spawnportal.cpp +++ b/src/spell/spell_spawnportal.cpp @@ -49,6 +49,11 @@ this->PortalType = 0; DebugPrint("unit type \"%s\" not found for spawn-portal.\n" _C_ value); } + } else if (!strcmp(value, "time-to-live")) { + this->TTL = LuaToNumber(l, -1, j + 1); + } else if (!strcmp(value, "current-player")) { + this->CurrentPlayer = true; + --j; } else { LuaError(l, "Unsupported spawn-portal tag: %s" _C_ value); } @@ -75,11 +80,13 @@ CUnit *portal = caster.Goal; DebugPrint("Spawning a portal exit.\n"); - if (portal) { + if (portal && portal->IsAlive()) { portal->MoveToXY(goalPos); } else { - portal = MakeUnitAndPlace(goalPos, *this->PortalType, &Players[PlayerNumNeutral]); + portal = MakeUnitAndPlace(goalPos, *this->PortalType, + CurrentPlayer ? caster.Player : &Players[PlayerNumNeutral]); } + portal->TTL = GameCycle + this->TTL; // Goal is used to link to destination circle of power caster.Goal = portal; //FIXME: setting destination circle of power should use mana diff --git a/src/ui/mouse.cpp b/src/ui/mouse.cpp index 656bcbf64..814765c00 100644 --- a/src/ui/mouse.cpp +++ b/src/ui/mouse.cpp @@ -259,7 +259,7 @@ static bool DoRightButton_Harvest(CUnit &unit, CUnit *dest, const Vec2i &pos, in PlayUnitSound(unit, VoiceAcknowledging); acknowledged = 1; } - if (dest->Type->CanMove() == false) { + if (dest->Type->CanMove() == false && !dest->Type->Teleporter) { SendCommandMove(unit, pos, flush); } else { SendCommandFollow(unit, *dest, flush); @@ -309,7 +309,7 @@ static void DoRightButton_Attack(CUnit &unit, CUnit *dest, const Vec2i &pos, int PlayUnitSound(unit, VoiceAcknowledging); acknowledged = 1; } - if (dest->Type->CanMove() == false) { + if (dest->Type->CanMove() == false && !dest->Type->Teleporter) { SendCommandMove(unit, pos, flush); } else { SendCommandFollow(unit, *dest, flush); @@ -369,7 +369,7 @@ static bool DoRightButton_Follow(CUnit &unit, CUnit &dest, int flush, int &ackno PlayUnitSound(unit, VoiceAcknowledging); acknowledged = 1; } - if (dest.Type->CanMove() == false) { + if (dest.Type->CanMove() == false && !dest.Type->Teleporter) { SendCommandMove(unit, dest.tilePos, flush); } else { SendCommandFollow(unit, dest, flush);