[Scripts] DBScripts-Engine: Implement new commands
* Add SCRIPT_COMMAND_MOVE_DYNAMIC to move to a random point or towards another unit * Toggle GetRandomPoint function to be able to return a random point with min-distance or a given direction. * Toggle MovementGenerator::GetResetPosition to be able to return a reasonable orientation for reset. Ideas and requirement research by virusav! Thanks to virusav and Grz3s for test-feedback! (c2603)
This commit is contained in:
parent
beb3522e2a
commit
4819ec8ebc
@ -1 +1 @@
|
||||
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
|
@ -168,6 +168,13 @@ ID | Name | Parameters
|
||||
34 | SCRIPT_COMMAND_TERMINATE_COND | `datalong` = condition_id, `datalong2` = fail-quest (if provided this quest will be failed for a player), `!(data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL)`: terminate when condition is true, `data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL`: terminate when condition is false
|
||||
35 | SCRIPT_COMMAND_SEND_AI_EVENT_AROUND | resultingSource = Creature, resultingTarget = Unit, datalong = AIEventType - limited only to EventAI supported events, datalong2 = radius
|
||||
36 | SCRIPT_COMMAND_TURN_TO | resultingSource = Creature, resultingTarget = Unit/none.
|
||||
37 | SCRIPT_COMMAND_MOVE_DYNAMIC | Move resultingSource to a random point around resultingTarget or to resultingTarget
|
||||
| * resultingSource = Creature, resultingTarget Worldobject.
|
||||
| * datalong = 0: Move resultingSource towards resultingTarget
|
||||
| * datalong != 0: Move resultingSource to a random point between datalong2..datalong around resultingTarget.
|
||||
| orientation != 0: Obtain a random point around resultingTarget in direction of orientation
|
||||
| * data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL Obtain a point in direction of resTarget->GetOrientation + orientation
|
||||
| for resTarget == resSource and orientation == 0 this will mean resSource moving forward
|
||||
|
||||
TemporaryFactionFlags
|
||||
---------------------
|
||||
|
@ -47,12 +47,11 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature& owner)
|
||||
Movement::MoveSplineInit init(owner);
|
||||
float x, y, z, o;
|
||||
// at apply we can select more nice return points base at current movegen
|
||||
if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner, x, y, z))
|
||||
if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner, x, y, z, o))
|
||||
{
|
||||
owner.GetRespawnCoord(x, y, z, &o);
|
||||
init.SetFacing(o);
|
||||
}
|
||||
|
||||
init.SetFacing(o);
|
||||
init.MoveTo(x, y, z, true);
|
||||
init.SetWalk(false);
|
||||
init.Launch();
|
||||
|
@ -59,7 +59,7 @@ class MovementGenerator
|
||||
virtual void unitSpeedChanged() { }
|
||||
|
||||
// used by Evade code for select point to evade with expected restart default movement
|
||||
virtual bool GetResetPosition(Unit&, float& /*x*/, float& /*y*/, float& /*z*/) const { return false; }
|
||||
virtual bool GetResetPosition(Unit&, float& /*x*/, float& /*y*/, float& /*z*/, float& o) const { return false; }
|
||||
|
||||
// given destination unreachable? due to pathfinsing or other
|
||||
virtual bool IsReachable() const { return true; }
|
||||
@ -98,10 +98,10 @@ class MovementGeneratorMedium : public MovementGenerator
|
||||
// u->AssertIsType<T>();
|
||||
return (static_cast<D*>(this))->Update(*((T*)&u), time_diff);
|
||||
}
|
||||
bool GetResetPosition(Unit& u, float& x, float& y, float& z) const override
|
||||
bool GetResetPosition(Unit& u, float& x, float& y, float& z, float& o) const override
|
||||
{
|
||||
// u->AssertIsType<T>();
|
||||
return (static_cast<D const*>(this))->GetResetPosition(*((T*)&u), x, y, z);
|
||||
return (static_cast<D const*>(this))->GetResetPosition(*((T*)&u), x, y, z, o);
|
||||
}
|
||||
public:
|
||||
// Will not link if not overridden in the generators
|
||||
@ -112,7 +112,7 @@ class MovementGeneratorMedium : public MovementGenerator
|
||||
bool Update(T& u, const uint32& time_diff);
|
||||
|
||||
// not need always overwrites
|
||||
bool GetResetPosition(T& /*u*/, float& /*x*/, float& /*y*/, float& /*z*/) const { return false; }
|
||||
bool GetResetPosition(T& /*u*/, float& /*x*/, float& /*y*/, float& /*z*/, float& /*o*/) const { return false; }
|
||||
};
|
||||
|
||||
struct SelectableMovement : public FactoryHolder<MovementGenerator, MovementGeneratorType>
|
||||
|
@ -254,32 +254,6 @@ bool WaypointMovementGenerator<Creature>::Update(Creature& creature, const uint3
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature& creature)
|
||||
{
|
||||
if (creature.AI())
|
||||
{ creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); }
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z) const
|
||||
{
|
||||
// prevent a crash at empty waypoint path.
|
||||
if (!i_path || i_path->empty())
|
||||
{ return false; }
|
||||
|
||||
WaypointPath::const_iterator lastPoint = i_path->find(m_lastReachedWaypoint);
|
||||
// Special case: Before the first waypoint is reached, m_lastReachedWaypoint is set to 0 (which may not be contained in i_path)
|
||||
if (!m_lastReachedWaypoint && lastPoint == i_path->end())
|
||||
{ return false; }
|
||||
|
||||
MANGOS_ASSERT(lastPoint != i_path->end());
|
||||
|
||||
const WaypointNode &waypoint = lastPoint->second;
|
||||
|
||||
x = waypoint.x;
|
||||
y = waypoint.y;
|
||||
z = waypoint.z;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::Stopped(Creature& u)
|
||||
{
|
||||
@ -295,6 +269,54 @@ bool WaypointMovementGenerator<Creature>::CanMove(int32 diff, Creature& u)
|
||||
return i_nextMoveTime.Passed() && !u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED);
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z, float& o) const
|
||||
{
|
||||
// prevent a crash at empty waypoint path.
|
||||
if (!i_path || i_path->empty())
|
||||
{ return false; }
|
||||
|
||||
WaypointPath::const_iterator lastPoint = i_path->find(m_lastReachedWaypoint);
|
||||
// Special case: Before the first waypoint is reached, m_lastReachedWaypoint is set to 0 (which may not be contained in i_path)
|
||||
if (!m_lastReachedWaypoint && lastPoint == i_path->end())
|
||||
{ return false; }
|
||||
|
||||
MANGOS_ASSERT(lastPoint != i_path->end());
|
||||
|
||||
WaypointNode const* curWP = &(lastPoint->second);
|
||||
|
||||
x = curWP->x;
|
||||
y = curWP->y;
|
||||
z = curWP->z;
|
||||
|
||||
if (curWP->orientation != 100)
|
||||
o = curWP->orientation;
|
||||
else // Calculate the resulting angle based on positions between previous and current waypoint
|
||||
{
|
||||
WaypointNode const* prevWP;
|
||||
if (lastPoint != i_path->begin()) // Not the first waypoint
|
||||
{
|
||||
--lastPoint;
|
||||
prevWP = &(lastPoint->second);
|
||||
}
|
||||
else // Take the last waypoint (crbegin()) as previous
|
||||
prevWP = &(i_path->rbegin()->second);
|
||||
|
||||
float dx = x - prevWP->x;
|
||||
float dy = y - prevWP->y;
|
||||
o = atan2(dy, dx); // returns value between -Pi..Pi
|
||||
|
||||
o = (o >= 0) ? o : 2 * M_PI_F + o;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature& creature)
|
||||
{
|
||||
if (creature.AI())
|
||||
{ creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); }
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::AddToWaypointPauseTime(int32 waitTimeDiff)
|
||||
{
|
||||
if (!i_nextMoveTime.Passed())
|
||||
@ -410,9 +432,12 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
||||
}
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z) const
|
||||
bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z, float& o) const
|
||||
{
|
||||
const TaxiPathNodeEntry& node = (*i_path)[i_currentNode];
|
||||
x = node.x; y = node.y; z = node.z;
|
||||
x = node.x;
|
||||
y = node.y;
|
||||
z = node.z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class WaypointMovementGenerator<Creature>
|
||||
// now path movement implmementation
|
||||
void LoadPath(Creature& c);
|
||||
|
||||
bool GetResetPosition(Creature&, float& x, float& y, float& z) const;
|
||||
bool GetResetPosition(Creature&, float& /*x*/, float& /*y*/, float& /*z*/, float& /*o*/) const;
|
||||
|
||||
void AddToWaypointPauseTime(int32 waitTimeDiff);
|
||||
|
||||
@ -132,7 +132,7 @@ class FlightPathMovementGenerator
|
||||
bool HasArrived() const { return (i_currentNode >= i_path->size()); }
|
||||
void SetCurrentNodeAfterTeleport();
|
||||
void SkipCurrentNode() { ++i_currentNode; }
|
||||
bool GetResetPosition(Player&, float& x, float& y, float& z) const;
|
||||
bool GetResetPosition(Player&, float& /*x*/, float& /*y*/, float& /*z*/, float& /*o*/) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1262,7 +1262,7 @@ bool WorldObject::isInBack(WorldObject const* target, float distance, float arc)
|
||||
return IsWithinDist(target, distance) && !HasInArc(2 * M_PI_F - arc, target);
|
||||
}
|
||||
|
||||
void WorldObject::GetRandomPoint(float x, float y, float z, float distance, float& rand_x, float& rand_y, float& rand_z) const
|
||||
void WorldObject::GetRandomPoint(float x, float y, float z, float distance, float& rand_x, float& rand_y, float& rand_z, float minDist /*=0.0f*/, float const* ori /*=NULL*/) const
|
||||
{
|
||||
if (distance == 0)
|
||||
{
|
||||
@ -1273,8 +1273,17 @@ void WorldObject::GetRandomPoint(float x, float y, float z, float distance, floa
|
||||
}
|
||||
|
||||
// angle to face `obj` to `this`
|
||||
float angle = rand_norm_f() * 2 * M_PI_F;
|
||||
float new_dist = rand_norm_f() * distance;
|
||||
float angle;
|
||||
if (!ori)
|
||||
angle = rand_norm_f() * 2 * M_PI_F;
|
||||
else
|
||||
angle = *ori;
|
||||
|
||||
float new_dist;
|
||||
if (minDist == 0.0f)
|
||||
new_dist = rand_norm_f() * distance;
|
||||
else
|
||||
new_dist = minDist + rand_norm_f() * (distance - minDist);
|
||||
|
||||
rand_x = x + new_dist * cos(angle);
|
||||
rand_y = y + new_dist * sin(angle);
|
||||
|
@ -540,7 +540,7 @@ class WorldObject : public Object
|
||||
void UpdateGroundPositionZ(float x, float y, float& z) const;
|
||||
void UpdateAllowedPositionZ(float x, float y, float& z) const;
|
||||
|
||||
void GetRandomPoint(float x, float y, float z, float distance, float& rand_x, float& rand_y, float& rand_z) const;
|
||||
void GetRandomPoint(float x, float y, float z, float distance, float& rand_x, float& rand_y, float& rand_z, float minDist = 0.0f, float const* ori = NULL) const;
|
||||
|
||||
uint32 GetMapId() const { return m_mapId; }
|
||||
uint32 GetInstanceId() const { return m_InstanceId; }
|
||||
|
@ -87,6 +87,10 @@ uint8 GetSpellStartDBScriptPriority(SpellEntry const* spellinfo, SpellEffectInde
|
||||
if (spellinfo->Effect[effIdx] == SPELL_EFFECT_TRIGGER_SPELL && !sSpellStore.LookupEntry(spellinfo->EffectTriggerSpell[effIdx]))
|
||||
{ return 5; }
|
||||
|
||||
// NonExisting trigger missile spells can also start DB-Spell-Scripts
|
||||
if (spellinfo->Effect[effIdx] == SPELL_EFFECT_TRIGGER_MISSILE && !sSpellStore.LookupEntry(spellinfo->EffectTriggerSpell[effIdx]))
|
||||
{ return 4; }
|
||||
|
||||
// Can not start script
|
||||
return 0;
|
||||
}
|
||||
@ -678,6 +682,15 @@ void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_MOVE_DYNAMIC: // 37
|
||||
{
|
||||
if (tmp.moveDynamic.maxDist < tmp.moveDynamic.minDist)
|
||||
{
|
||||
sLog.outErrorDb("Table `%s` has invalid min-dist (datalong2 = %u) less than max-dist (datalon = %u) in SCRIPT_COMMAND_MOVE_DYNAMIC for script id %u", tablename, tmp.moveDynamic.minDist, tmp.moveDynamic.maxDist, tmp.id);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
sLog.outErrorDb("Table `%s` unknown command %u, skipping.", tablename, tmp.command);
|
||||
@ -1065,6 +1078,15 @@ bool ScriptAction::LogIfNotGameObject(WorldObject* pWorldObject)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ScriptAction::LogIfNotPlayer(WorldObject* pWorldObject)
|
||||
{
|
||||
if (!pWorldObject || pWorldObject->GetTypeId() != TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u call for non-player, skipping.", m_table, m_script->id, m_script->command);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Helper to get a player if possible (target preferred)
|
||||
Player* ScriptAction::GetPlayerTargetOrSourceAndLog(WorldObject* pSource, WorldObject* pTarget)
|
||||
@ -1442,12 +1464,12 @@ bool ScriptAction::HandleScriptStep()
|
||||
|
||||
// Select Spell
|
||||
uint32 spell = m_script->castSpell.spellId;
|
||||
uint32 i = 0;
|
||||
while (i < MAX_TEXT_ID && m_script->textId[i]) // Count which dataint fields are filled
|
||||
++i;
|
||||
if (i > 0)
|
||||
if (uint32 rnd = urand(0, i)) // Random selection resulted in one of the dataint fields
|
||||
spell = m_script->textId[rnd - 1];
|
||||
uint32 filledCount = 0;
|
||||
while (filledCount < MAX_TEXT_ID && m_script->textId[filledCount]) // Count which dataint fields are filled
|
||||
++filledCount;
|
||||
if (filledCount > 0)
|
||||
if (uint32 randomField = urand(0, filledCount)) // Random selection resulted in one of the dataint fields
|
||||
spell = m_script->textId[randomField - 1];
|
||||
|
||||
// TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast
|
||||
if (pSource && pSource->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
@ -1824,6 +1846,39 @@ bool ScriptAction::HandleScriptStep()
|
||||
((Unit*)pSource)->SetFacingTo(pSource->GetAngle(pTarget));
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_MOVE_DYNAMIC: // 37
|
||||
{
|
||||
if (LogIfNotCreature(pSource))
|
||||
return false;
|
||||
if (LogIfNotUnit(pTarget))
|
||||
return false;
|
||||
|
||||
float x, y, z;
|
||||
if (m_script->moveDynamic.maxDist == 0) // Move to pTarget
|
||||
{
|
||||
if (pTarget == pSource)
|
||||
{
|
||||
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, _MOVE_DYNAMIC called with maxDist == 0, but resultingSource == resultingTarget (== %s)", m_table, m_script->id, pSource->GetGuidStr().c_str());
|
||||
break;
|
||||
}
|
||||
pTarget->GetContactPoint(pSource, x, y, z);
|
||||
}
|
||||
else // Calculate position
|
||||
{
|
||||
float orientation;
|
||||
if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL)
|
||||
orientation = pSource->GetOrientation() + m_script->o + 2 * M_PI_F;
|
||||
else
|
||||
orientation = m_script->o;
|
||||
|
||||
pSource->GetRandomPoint(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), m_script->moveDynamic.maxDist, x, y, z,
|
||||
m_script->moveDynamic.minDist, (orientation == 0.0f ? NULL : &orientation));
|
||||
z = std::max(z, pTarget->GetPositionZ());
|
||||
pSource->UpdateAllowedPositionZ(x, y, z);
|
||||
}
|
||||
((Creature*)pSource)->GetMotionMaster()->MovePoint(1, x, y, z);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outErrorDb(" DB-SCRIPTS: Process table `%s` id %u, command %u unknown command used.", m_table, m_script->id, m_script->command);
|
||||
break;
|
||||
|
@ -111,6 +111,12 @@ enum ScriptCommand // resSource, resTar
|
||||
// datalong = AIEventType
|
||||
// datalong2 = radius
|
||||
SCRIPT_COMMAND_TURN_TO = 36, // resSource = Unit, resTarget = Unit/none
|
||||
SCRIPT_COMMAND_MOVE_DYNAMIC = 37, // resSource = Creature, resTarget Worldobject.
|
||||
// datalong = 0: Move resSource towards resTarget
|
||||
// datalong != 0: Move resSource to a random point between datalong2..datalong around resTarget.
|
||||
// orientation != 0: Obtain a random point around resTarget in direction of orientation
|
||||
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL Obtain a random point around resTarget in direction of resTarget->GetOrientation + orientation
|
||||
// for resTarget == resSource and orientation == 0 this will mean resSource moving forward
|
||||
};
|
||||
|
||||
#define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK, SCRIPT_COMMAND_EMOTE, SCRIPT_COMMAND_CAST_SPELL, SCRIPT_COMMAND_TERMINATE_SCRIPT
|
||||
@ -339,17 +345,23 @@ struct ScriptInfo
|
||||
uint32 radius; // datalong2
|
||||
} sendAIEvent;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 data[2];
|
||||
} raw;
|
||||
|
||||
struct // SCRIPT_COMMAND_TURN_TO (36)
|
||||
{
|
||||
uint32 targetId; // datalong
|
||||
uint32 empty1; // datalong2
|
||||
} turnTo;
|
||||
|
||||
struct // SCRIPT_COMMAND_MOVE_DYNAMIC (37)
|
||||
{
|
||||
uint32 maxDist; // datalong
|
||||
uint32 minDist; // datalong2
|
||||
} moveDynamic;
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 data[2];
|
||||
} raw;
|
||||
};
|
||||
|
||||
// Buddy system (entry can be npc or go entry, depending on command)
|
||||
@ -406,6 +418,8 @@ struct ScriptInfo
|
||||
case SCRIPT_COMMAND_MOUNT_TO_ENTRY_OR_MODEL:
|
||||
case SCRIPT_COMMAND_TERMINATE_SCRIPT:
|
||||
case SCRIPT_COMMAND_TERMINATE_COND:
|
||||
case SCRIPT_COMMAND_TURN_TO:
|
||||
case SCRIPT_COMMAND_MOVE_DYNAMIC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -465,6 +479,7 @@ class ScriptAction
|
||||
bool LogIfNotCreature(WorldObject* pWorldObject);
|
||||
bool LogIfNotUnit(WorldObject* pWorldObject);
|
||||
bool LogIfNotGameObject(WorldObject* pWorldObject);
|
||||
bool LogIfNotPlayer(WorldObject* pWorldObject);
|
||||
Player* GetPlayerTargetOrSourceAndLog(WorldObject* pSource, WorldObject* pTarget);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user