2007年4月3日 星期二

mangos 恐懼的修正

發現在打2王時..它一放恐懼結果我的人物上下到處亂跑,最後掉下來摔死@@
底下是修正的程式碼,不過有缺點...變成被恐懼後...並不會到處跑@@

看討論是說,不應該用SendMonsterMove或Relocate這2個函式
不過我試了Map::CreatureRelocation及Map::PlayerRelocation一樣也是不行@@
感覺上都是Z座標在作怪,一點點問題就會造成Server Crash掉.

Index: src/game/FearedMovementGenerator.cpp
===================================================================
--- src/game/FearedMovementGenerator.cpp (revision 0)
+++ src/game/FearedMovementGenerator.cpp (revision 0)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2005,2006 MaNGOS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Creature.h"
+#include "MapManager.h"
+#include "Opcodes.h"
+#include "FearedMovementGenerator.h"
+#include "DestinationHolderImp.h"
+
+void
+FearedMovementGenerator::Initialize(Creature &creature)
+{
+}
+
+void
+FearedMovementGenerator::Initialize(Creature &creature, WorldObject *caster)
+{
+ float distance,dist;
+ float x,y,z,z2,angle;
+ x = creature.GetPositionX();
+ y = creature.GetPositionY();
+ z = creature.GetPositionZ();
+ angle = caster->GetAngle((WorldObject*)&creature);
+ uint32 mapid=creature.GetMapId();
+ i_caster=caster;
+ creature.setMoveRunFlag(true);
+ i_nextMove = 0;
+
+ Map* map = MapManager::Instance().GetMap(mapid);
+ z2 = map->GetHeight(x,y);
+ if( abs( z2 - z ) > 5 )
+ {
+ CreatureTraveller traveller(creature);
+ i_destinationHolder.SetDestination(traveller, x, y, z); //override setdest tergetedmovementgen
+ return;
+ }
+
+
+ distance = 5;
+ int leftright=urand(0,1);
+ bool is_water_ok = creature.isCanSwimOrFly();
+ bool is_land_ok = creature.isCanWalkOrFly();
+
+ for(unsigned int idx=0; idx < MAX_FEAR_WAYPOINTS+1; ++idx)
+ {
+
+ if(urand(0,100)<30)
+ {
+ angle=angle+(M_PI*(float)rand()/RAND_MAX/2-M_PI/4);
+ leftright=urand(0,1);
+ }
+ if(idx>0)
+ {
+ dist=caster->GetDistanceSq(i_waypoints[idx-1][0],i_waypoints[idx-1][1],i_waypoints[idx-1][2]);
+ if(dist>40*40)
+ {
+ float dx = caster->GetPositionX() - i_waypoints[idx-1][0];
+ float dy = caster->GetPositionY() - i_waypoints[idx-1][1];
+ float ang = atan2(dy, dx);
+ ang = (ang >= 0) ? ang : 2 * M_PI + ang;
+ if(leftright)angle=ang+M_PI*(float)rand()/RAND_MAX/6+5*M_PI/12;
+ else angle=ang-M_PI*(float)rand()/RAND_MAX/6-5*M_PI/12;
+ }
+ i_waypoints[idx][0] = i_waypoints[idx-1][0] + distance*cos(angle);
+ i_waypoints[idx][1] = i_waypoints[idx-1][1] + distance*sin(angle);
+ }
+ else
+ {
+ dist=caster->GetDistanceSq(x,y,z);
+ if(dist>40*40)
+ {
+ float dx = caster->GetPositionX() - x;
+ float dy = caster->GetPositionY() - y;
+ float ang = atan2(dy, dx);
+ ang = (ang >= 0) ? ang : 2 * M_PI + ang;
+ if(leftright)angle=ang+M_PI*(float)rand()/RAND_MAX/6+5*M_PI/12;
+ else angle=ang-M_PI*(float)rand()/RAND_MAX/6-5*M_PI/12;
+ }
+ i_waypoints[idx][0] = x + distance*cos(angle);
+ i_waypoints[idx][1] = y + distance*sin(angle);
+ }
+
+ // prevent invalid coordinates generation
+ MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]);
+ MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]);
+
+ bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1]);
+
+ // if generated wrong path just ignore
+ if( is_water && !is_water_ok || !is_water && !is_land_ok )
+ {
+ i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
+ i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
+ }
+
+ z2 = map->GetHeight(i_waypoints[idx][0],i_waypoints[idx][1]);
+ if( abs( z2 - z ) < 5 )
+ z=z2;
+ i_waypoints[idx][2] = z;
+ }
+
+ CreatureTraveller traveller(creature);
+ i_nextMove = 0;
+ i_destinationHolder.SetDestination(traveller, i_waypoints[i_nextMove][0], i_waypoints[i_nextMove][1], i_waypoints[i_nextMove][2]);
+
+}
+
+
+void
+FearedMovementGenerator::Reset(Creature &creature)
+{
+}
+
+bool
+FearedMovementGenerator::Update(Creature &creature, const uint32 &diff)
+{
+ if(!&creature)
+ return true;
+ if(creature.hasUnitState(UNIT_STAT_ROOT) || creature.hasUnitState(UNIT_STAT_STUNDED))
+ return true;
+
+ float x,y,z,z2;
+ x = creature.GetPositionX();
+ y = creature.GetPositionY();
+ z = creature.GetPositionZ();
+ uint32 mapid=creature.GetMapId();
+ Map* map = MapManager::Instance().GetMap(mapid);
+ z2 = map->GetHeight(x,y);
+ if( abs( z2 - z ) > 5 )
+ return true;
+
+ CreatureTraveller traveller(creature);
+
+ if(i_destinationHolder.HasArrived())
+ {
+ if(i_needUpdate)
+ {
+ if(!i_caster)return true;
+ Initialize(creature,i_caster);
+ i_needUpdate=false;
+ }
+ else if(i_nextMove < MAX_FEAR_WAYPOINTS)
+ {
+ i_destinationHolder.SetDestination(traveller, i_waypoints[i_nextMove][0], i_waypoints[i_nextMove][1], i_waypoints[i_nextMove][2]);
+ i_nextMove++;
+ }
+ else
+ {
+ if(!i_caster)return true;
+ Initialize(creature,i_caster);
+ }
+ }
+
+ if(i_destinationHolder.UpdateTraveller(traveller,diff,false))
+ {
+ i_destinationHolder.ResetUpdate(50);
+ }
+
+ return true;
+}
+
+int
+FearedMovementGenerator::Permissible(const Creature *creature)
+{
+ return FEARED_MOTION_TYPE;
+}
Index: src/game/FearedMovementGenerator.h
===================================================================
--- src/game/FearedMovementGenerator.h (revision 0)
+++ src/game/FearedMovementGenerator.h (revision 0)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005,2006 MaNGOS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOS_FEAREDMOVEMENTGENERATOR_H
+#define MANGOS_FEAREDMOVEMENTGENERATOR_H
+
+#include "MovementGenerator.h"
+#include "DestinationHolder.h"
+#include "Traveller.h"
+
+#define MAX_FEAR_WAYPOINTS 15
+
+class MANGOS_DLL_DECL FearedMovementGenerator : public MovementGenerator
+{
+ public:
+ FearedMovementGenerator(const Creature &) {}
+
+ void Initialize(Creature &);
+ void Initialize(Creature &creature, WorldObject *caster);
+ void Reset(Creature &);
+ bool Update(Creature &, const uint32 &);
+ MovementGeneratorType GetMovementGeneratorType() { return FEARED_MOTION_TYPE; }
+ void NeedUpdate() {i_needUpdate = true;};
+ static int Permissible(const Creature *);
+ private:
+ float i_waypoints[MAX_FEAR_WAYPOINTS+1][3];
+ DestinationHolder< CreatureTraveller > i_destinationHolder;
+ uint32 i_nextMove;
+ WorldObject* i_caster;
+ bool i_needUpdate;
+
+};
+#endif
Index: src/game/MovementGenerator.h
===================================================================
--- src/game/MovementGenerator.h (revision 3326)
+++ src/game/MovementGenerator.h (working copy)
@@ -40,7 +40,8 @@
CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h
TARGETED_MOTION_TYPE = 5, // TargetedMovementGenerator.h
TAXI_MOTION_TYPE = 6, // TaxiMovementGenerator.h
- HOME_MOTION_TYPE = 7 // HomeMovementGenerator.h
+ HOME_MOTION_TYPE, // HomeMovementGenerator.h
+ FEARED_MOTION_TYPE
};

class MANGOS_DLL_SPEC MovementGenerator
Index: src/game/Spell.cpp
===================================================================
--- src/game/Spell.cpp (revision 3326)
+++ src/game/Spell.cpp (working copy)
@@ -1058,7 +1058,8 @@
// check for incapacitating player states
if( m_caster->hasUnitState(UNIT_STAT_STUNDED) ||
m_caster->hasUnitState(UNIT_STAT_ROOT) ||
- m_caster->hasUnitState(UNIT_STAT_CONFUSED) )
+ m_caster->hasUnitState(UNIT_STAT_CONFUSED) ||
+ m_caster->hasUnitState(UNIT_STAT_FLEEING))
cancel();

// check if player has turned if flag is set
Index: src/game/SpellAuras.cpp
===================================================================
--- src/game/SpellAuras.cpp (revision 3326)
+++ src/game/SpellAuras.cpp (working copy)
@@ -42,6 +42,8 @@
#include "Creature.h"
#include "ConfusedMovementGenerator.h"
#include "Formulas.h"
+#include "FearedMovementGenerator.h"
+#include "TargetedMovementGenerator.h"

pAuraHandler AuraHandler[TOTAL_AURAS]=
{
@@ -366,25 +368,13 @@
pos_y = m_target->GetPositionY();
uint32 mapid = m_target->GetMapId();
pos_z = MapManager::Instance().GetMap(mapid)->GetHeight(pos_x,pos_y);
- // Control the max Distance; 20 for temp.
- if(m_target->IsWithinDist(caster, 20))
- {
- if( m_target->GetPositionX() < caster->GetPositionX() || m_target->GetPositionY() > caster->GetPositionY() )
- x = m_target->GetPositionX() + speed*diff * sin(angle)/1000;
- else
- x = m_target->GetPositionX() - speed*diff * sin(angle)/1000;
- y = m_target->GetPositionY() - speed*diff * cos(angle)/1000;
- mapid = m_target->GetMapId();
- z = MapManager::Instance().GetMap(mapid)->GetHeight(x,y);
- // Control the target to not climb or drop when dz > |x|,x = 1.3 for temp.
- // fixed me if it needs checking when the position will be in water?
- if(z <= pos_z+1.3 && z>=pos_z-1.3)
- {
- m_target->SendMonsterMove(x,y,z,false,true,diff);
- if(m_target->GetTypeId() != TYPEID_PLAYER)
- m_target->Relocate(x,y,z,m_target->GetOrientation());
- }
- }
+ z = MapManager::Instance().GetMap(m_target->GetMapId())->GetHeight(pos_x,pos_y);
+ if( (abs( z - pos_z ) < 5) && m_target->IsWithinDist(caster,15) && (m_target->GetTypeId() == TYPEID_UNIT))
+ {
+ static_cast< FearedMovementGenerator *>((*(Creature*)m_target)->top())->NeedUpdate();
+ }
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ m_target->SendMonsterMove(pos_x,pos_y,pos_z,false,true,diff);
}
}

@@ -1537,12 +1527,21 @@
uint32 apply_stat = UNIT_STAT_FLEEING;
if( Apply )
{
+ Unit* caster = GetCaster();
+ if(!caster)return;
+
m_target->addUnitState(UNIT_STAT_FLEEING);
// m_target->AttackStop();

m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat << 16));

- // only at real add aura
+ if (m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ (*(Creature*)m_target)->Mutate(new FearedMovementGenerator(*(Creature*)m_target));
+ static_cast((*(Creature*)m_target)->top())->Initialize(*((Creature*)m_target),(WorldObject*)caster);
+ }
+
+ // only at real add aura
if(Real)
{
WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 9);
@@ -1556,6 +1555,16 @@
m_target->clearUnitState(UNIT_STAT_FLEEING);
m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat << 16));

+ if (m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ (*(Creature*)m_target)->MovementExpired();
+ static_cast< TargetedMovementGenerator *>((*(Creature*)m_target)->top())->Reset(*(Creature*)m_target);
+ }
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat << 16));
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ m_target->Attack(GetCaster());
+
// only at real remove aura
if(Real)
{



--- /home/matt/mangos-cvs/src/game/SpellAuras.cpp 2007-01-04 15:30:04.000000000 -0700
+++ SpellAuras.cpp 2007-01-03 23:15:30.000000000 -0700
@@ -372,8 +372,7 @@
speed = m_target->GetSpeed(MOVE_RUN);
pos_x = m_target->GetPositionX();
pos_y = m_target->GetPositionY();
- uint32 mapid = m_target->GetMapId();
- pos_z = MapManager::Instance().GetMap(mapid)->GetHeight(pos_x,pos_y);
+ pos_z = m_target->GetPositionZ();
// Control the max Distance; 20 for temp.
if(m_target->IsWithinDist(caster, 20))
{
@@ -382,8 +381,7 @@
else
x = m_target->GetPositionX() - speed*diff * sin(angle)/1000;
y = m_target->GetPositionY() - speed*diff * cos(angle)/1000;
- mapid = m_target->GetMapId();
- z = MapManager::Instance().GetMap(mapid)->GetHeight(x,y);
+ z = m_target->GetPositionZ();
// Control the target to not climb or drop when dz > |x|,x = 1.3 for temp.
// fixed me if it needs checking when the position will be in water?
if(z<=pos_z+1.3 && z>=pos_z-1.3)

沒有留言: