* added experimental character movement (jump/strafe not yet done). press POS1/Home key to toggle camera/character WASD movement. camera NOT yet linked to character!!

* conf supports now client 2.4.2. no code changes.
* packets can now be sent not only from the PseuInstance main thread
* added new conf option "softquit" to disable instant terminate (+data loss) on win32 systems if user [X]'ed console window.
* misc fixes & code changes

(personal note: exams are over, back to coding, yay)
This commit is contained in:
false_genesis 2008-06-08 19:49:00 +00:00
parent 926a7566c8
commit 7780f608da
21 changed files with 519 additions and 126 deletions

View File

@ -16,6 +16,12 @@ debug=0
// defines if the program should quit on error/exception or stay opened (for debugging)
exitonerror=0
// shutdown instead of terminating forcefully when user clicks the [X] (close) button.
// If this is disabled, you have to close PseuWoW with Ctrl+C or by typing "exit" into the console to save data!
// The problem is that windows usually gives processes 5 secs time to close after clicking [X], if they don't, they are marked as crashed.
// Default: 1 (enabled) -- [Win32 only]
softquit=1
// reconnect on failure/disconnect
// 0 = dont't reconnect
// everything else: delay (in ms) until the next connection attempt.
@ -62,8 +68,8 @@ charname=Pseuwow
// Client emulation configuration
ClientVersion=2.4.1
ClientBuild=8125
ClientVersion=2.4.2
ClientBuild=8278
ClientLanguage=enUS
// or change to enGB, deDE, ...
@ -127,7 +133,7 @@ SkipAddonChat=1
// Note that packet dumps are valid for 1 session only, the counter gets reset when the WorldSession is destroyed.
// This means they get overwritten if not saved!
// 0 - no packet dumping
// 1 - dump packets that caused an excpetion or object update error
// 1 - dump packets that caused an exception or object update error
// 2 - like [1] + all packets with opcodes not handled by the core
// (doesn't matter if they have scripts attached or not, they will be dumped always)
DumpPackets=1

View File

@ -18,6 +18,9 @@ other_cmd_chars=.!
// Set to 1 if PseuWoW should exit after the GUI is closed (if there is a GUI)
ExitOnGUIClose=0
// Upon closing PseuWoW will say something you can specify here. Leave blank do disable.
ExitMessage=Terminating Proc...
[#normal]

View File

@ -283,6 +283,10 @@ name=Zul'Aman
name_general=PVPLordaeron
name=Ruins of Lordaeron
[580]
name_general=SunwellPlateau
name=The Sunwell
[582]
name_general=Transport176244
name=Transport: Rut'theran to Auberdine
@ -291,6 +295,10 @@ name=Transport: Rut'theran to Auberdine
name_general=Transport176231
name=Transport: Menethil to Theramore
[585]
name_general=Sunwell5ManFix
name=Magister's Terrace
[586]
name_general=Transport181645
name=Transport: Exodar to Auberdine
@ -319,3 +327,7 @@ name=Transport: Undercity to Orgrimmar
name_general=Transport20808
name=Transport: Booty Bay to Ratchet
[598]
name_general=Sunwell5Man
name=Sunwell Fix (Unused)

View File

@ -111,4 +111,16 @@ EMOTE 66 // say NO!
//- script content here
#script=_onexit
// called just before PseuWoW exits
// @0: error? (0/1)
if ${@inworld}
set,m ?{getvar #EXITMESSAGE}
if ?{strlen ${m}}
say ${m}
endif
unset m
endif

View File

@ -16,10 +16,6 @@ QUIT
#script=quit
#permission=255
//--------------------------------------------------------
// quit PseuWoW, say goodbye when logged in
IF ${@inworld}
SAY Terminating proc...
ENDIF
SHDN

View File

@ -34,6 +34,44 @@ public:
~MCameraFPS(){}
void update(void)
{
turnLeft(0);
turnUp(0);
moveForward(0);
}
/*
void setTarget(core::vector3df t)
{
direction = t - getTarget();
camera->setTarget(t);
rotationX = RADTODEG * asin(DEGTORAD * t.X);
rotationY = RADTODEG * (acos(DEGTORAD * t.Y) + (PI/2.0f));
if(rotationY>=360)rotationY-=360;
if(rotationY<0)rotationY+=360;
if(rotationX>=360)rotationX-=360;
if(rotationX<0)rotationX+=360;
direction.normalize();
}*/
void setRotationLeft(f32 i)
{
rotationY = i;
if(rotationY>=360)rotationY-=360;
if(rotationY<0)rotationY+=360;
direction = core::vector3df(0,0,1);
core::matrix4 matrix;
matrix.setRotationDegrees(core::vector3df (rotationX,rotationY,0));
matrix.rotateVect(direction);
camera->setTarget(camera->getPosition() + direction);
camera->updateAbsolutePosition();
}
void turnRight(f32 i)
{
rotationY += i;

View File

@ -185,36 +185,29 @@ void PseuGUI::Run(void)
_device->sleep(10); // save cpu & gpu power if not focused
}
try
_UpdateSceneState();
if(!_scene)
{
_UpdateSceneState();
if(!_scene)
{
_device->sleep(10);
continue;
}
_scene->OnUpdate(_passtimediff); // custom: process input, set camera, etc
_driver->beginScene(true, true, _scene->GetBackgroundColor()); // irr: call driver to start drawing
_scene->OnDrawBegin(); // custom: draw everything before irrlicht draws everything by itself
_smgr->drawAll(); // irr: draw all scene nodes
_guienv->drawAll(); // irr: draw gui elements
_scene->OnDraw(); // custom: draw everything that has to be draw late (post-processing also belongs here)
_driver->endScene(); // irr: drawing done
if(_driver->getFPS()>100 && _throttle < 10)//Primitive FPS-Limiter - upper cap hardcoded 100 FPS.
_throttle++; //lowercap 60 (if it drops below, limiting is eased).
if(_driver->getFPS()<60 && _throttle>0) //but honestly, a 10 msec delay is not worth this amount of code.
_throttle--; //If the FPS is down, it will never be because of this
if(_throttle>0) //Thus i opt for dropping the charade and using a fixed conf value of max 10.
_device->sleep(_throttle); //sleeps max 10 msec (=_throttle) here.
}
catch(...)
{
logerror("Unhandled exception in PseuGUI::Run() device=%X smgr=%X objects:%u", _device, _smgr, domgr.StorageSize());
_device->sleep(10);
continue;
}
_scene->OnUpdate(_passtimediff); // custom: process input, set camera, etc
_driver->beginScene(true, true, _scene->GetBackgroundColor()); // irr: call driver to start drawing
_scene->OnDrawBegin(); // custom: draw everything before irrlicht draws everything by itself
_smgr->drawAll(); // irr: draw all scene nodes
_guienv->drawAll(); // irr: draw gui elements
_scene->OnDraw(); // custom: draw everything that has to be draw late (post-processing also belongs here)
_driver->endScene(); // irr: drawing done
if(_driver->getFPS()>100 && _throttle < 10)//Primitive FPS-Limiter - upper cap hardcoded 100 FPS.
_throttle++; //lowercap 60 (if it drops below, limiting is eased).
if(_driver->getFPS()<60 && _throttle>0) //but honestly, a 10 msec delay is not worth this amount of code.
_throttle--; //If the FPS is down, it will never be because of this
if(_throttle>0) //Thus i opt for dropping the charade and using a fixed conf value of max 10.
_device->sleep(_throttle); //sleeps max 10 msec (=_throttle) here.
fps = _driver->getFPS();
if (lastFPS != fps)

View File

@ -78,6 +78,8 @@ class MCameraOrbit;
class MyEventReceiver;
class MapMgr;
class WorldSession;
class MovementMgr;
class MyCharacter;
class SceneWorld : public Scene
{
@ -117,6 +119,11 @@ private:
scene::ISceneNode *sky;
scene::ISceneNode *selectedNode, *oldSelectedNode, *focusedNode, *oldFocusedNode;
video::SColor envBasicColor;
MovementMgr *movemgr;
MyCharacter *mychar;
bool _freeCameraMove;
void _CalcXYMoveVect(float o);
core::vector2df xyCharMovement; // stores sin() and cos() values for current MyCharacter orientation, so that they need to be calculated only if the character turns around
};

View File

@ -12,17 +12,23 @@
#include "WorldSession.h"
#include "World.h"
#include "CCursorController.h"
#include "MovementMgr.h"
SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
{
DEBUG(logdebug("SceneWorld: Initializing..."));
debugmode = false;
_freeCameraMove = true;
// store some pointers right now to prevent repeated ptr dereferencing later (speeds up code)
gui = g;
wsession = gui->GetInstance()->GetWSession();
world = wsession->GetWorld();
mapmgr = world->GetMapMgr();
movemgr = world->GetMoveMgr();
mychar = wsession->GetMyChar();
ASSERT(mychar);
_CalcXYMoveVect(mychar->GetO());
ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(0,0,0), SColorf(255, 255, 255, 255), 1000.0f);
SLight ldata = light->getLightData();
@ -118,30 +124,176 @@ void SceneWorld::OnUpdate(s32 timediff)
selectedNode = focusedNode;
}*/ // i'll continue working on this - [FG]
if(eventrecv->key.pressed_once(KEY_KEY_L))
((ICameraSceneNode*)camera->getNode())->setTarget(vector3df(0,0,0));
// maybe it is better to replace the sin() and cos() with some irr::core::matrix4 calcualtions... not sure what is more efficient
if(eventrecv->key.pressed(KEY_KEY_W) || (mouse_pressed_left && mouse_pressed_right))
camera->moveForward(50 * timediff_f);
{
if(_freeCameraMove)
camera->moveForward(50 * timediff_f);
else
{
f32 speedfactor = timediff_f * mychar->GetSpeed(MOVE_RUN);
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveStartForward();
WorldPosition wp = mychar->GetPosition();
wp.x += (xyCharMovement.X * speedfactor);
wp.y += (xyCharMovement.Y * speedfactor);
wp.z = terrain->getHeight(WPToIrr(wp));
mychar->SetPosition(wp);
}
}
if(eventrecv->key.pressed(KEY_KEY_S))
camera->moveBack(50 * timediff_f);
if(eventrecv->key.pressed(KEY_KEY_E))
camera->moveRight(50 * timediff_f);
if(eventrecv->key.pressed(KEY_KEY_Q))
camera->moveLeft(50 * timediff_f);
{
if(_freeCameraMove)
camera->moveBack(50 * timediff_f);
else
{
f32 speedfactor = timediff_f * mychar->GetSpeed(MOVE_WALKBACK);
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveStartBackward();
WorldPosition wp = mychar->GetPosition();
wp.x -= (xyCharMovement.X * speedfactor);
wp.y -= (xyCharMovement.Y * speedfactor);
wp.z = terrain->getHeight(WPToIrr(wp));
mychar->SetPosition(wp);
}
}
// if right mouse button pressed, move in axis, if not, turn camera
if(eventrecv->key.pressed(KEY_KEY_D))
{
if(mouse_pressed_right)
camera->moveRight(50 * timediff_f);
{
if(_freeCameraMove)
camera->moveRight(50 * timediff_f);
else
{
// TODO: strafe case
}
}
else
camera->turnRight(timediff_f * M_PI * 25);
{
if(_freeCameraMove)
camera->turnRight(timediff_f * M_PI * 25);
else
{
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveStartTurnRight();
WorldPosition wp = mychar->GetPosition();
wp.z = terrain->getHeight(WPToIrr(wp));
wp.o -= (timediff_f * mychar->GetSpeed(MOVE_TURN));
wp.o = RAD_FIX(wp.o);
mychar->SetPosition(wp);
_CalcXYMoveVect(wp.o);
}
}
}
if(eventrecv->key.pressed(KEY_KEY_A))
{
if(mouse_pressed_right)
{
if(_freeCameraMove)
camera->moveLeft(50 * timediff_f);
else
{
// TODO: strafe case
}
}
else
{
if(_freeCameraMove)
camera->turnLeft(timediff_f * M_PI * 25);
else
{
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveStartTurnLeft();
WorldPosition wp = mychar->GetPosition();
wp.z = terrain->getHeight(WPToIrr(wp));
wp.o += (timediff_f * mychar->GetSpeed(MOVE_TURN));
wp.o = RAD_FIX(wp.o);
mychar->SetPosition(wp);
_CalcXYMoveVect(wp.o);
}
}
}
if(eventrecv->key.pressed(KEY_KEY_E))
{
if(_freeCameraMove)
camera->moveRight(50 * timediff_f);
else
{/*
f32 speedfactor = timediff_f * mychar->GetSpeed(MOVE_RUN);
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveStartStrafeRight();
WorldPosition wp = mychar->GetPosition();
wp.x -= (xyCharMovement.X * speedfactor);
wp.y -= (xyCharMovement.Y * speedfactor);
wp.z = terrain->getHeight(WPToIrr(wp));
mychar->SetPosition(wp);
*/}
}
if(eventrecv->key.pressed(KEY_KEY_Q))
{
if(_freeCameraMove)
camera->moveLeft(50 * timediff_f);
else
camera->turnLeft(timediff_f * M_PI * 25);
{/*
f32 speedfactor = timediff_f * mychar->GetSpeed(MOVE_RUN);
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveStartStrafeLeft();
WorldPosition wp = mychar->GetPosition();
wp.x -= (xyCharMovement.X * speedfactor);
wp.y -= (xyCharMovement.Y * speedfactor);
wp.z = terrain->getHeight(WPToIrr(wp));
mychar->SetPosition(wp);
*/}
}
/*if(eventrecv->key.pressed(KEY_SPACE))
{
movemgr->SetMoveMode(MOVEMODE_MANUAL);
movemgr->MoveJump();
}*/
// listen to *not* pressed keys only if manually moving
if(movemgr->GetMoveMode() == MOVEMODE_MANUAL)
{
if (!eventrecv->key.pressed(KEY_KEY_D) && !eventrecv->key.pressed(KEY_KEY_A))
{
movemgr->MoveStopTurn();
}
if (!eventrecv->key.pressed(KEY_KEY_W) && !eventrecv->key.pressed(KEY_KEY_S))
{
movemgr->MoveStop();
}
// TODO: add strafe case
}
// if we moved, relocate MyCharacter
/*if(movemgr->IsMoved())
{
MyCharacter *my = wsession->GetMyChar();
if(my)
{
WorldPosition newpos = GetWorldPosition();
my->SetPosition(newpos);
}
else
{
logerror("SceneWorld: Can't move MyCharacter, not found!");
}
}*/
if(eventrecv->key.pressed_once(KEY_HOME))
{
_freeCameraMove = !_freeCameraMove;
}
if(eventrecv->key.pressed_once(KEY_BACK))
@ -212,7 +364,7 @@ void SceneWorld::OnUpdate(s32 timediff)
DEBUG(
WorldPosition wp = GetWorldPosition();
str += L"Camera: pitch:";
str += L" Camera: pitch:";
str += camera->getPitch();
str += L" c pos:";
str += camera->getPosition().X;
@ -224,7 +376,7 @@ void SceneWorld::OnUpdate(s32 timediff)
str += " ## HEAD: ";
str += IRR_TO_O(camera->getHeading());
str += L" Pos: ";
str = ((((((str + wp.x) + L" | ") + wp.y) + L" | ") + wp.z) + L" | OR:") + wp.o;
str += ((((((str + wp.x) + L" | ") + wp.y) + L" | ") + wp.z) + L" | OR:") + wp.o;
str += L" -- Terrain: Sectors: ";
str += (int)terrain->getSectorsRendered();
str += L" / ";
@ -381,9 +533,12 @@ void SceneWorld::UpdateTerrain(void)
for(s32 tilex = 0; tilex < 3; tilex++)
{
MapTile *maptile = mapmgr->GetNearTile(tilex - 1, tiley - 1);
uint32 tile_real_x = mapmgr->GetGridX() + tilex - 1;
uint32 tile_real_y = mapmgr->GetGridY() + tiley - 1;
if(maptile)
{
// apply map height data
logdebug("Applying height data for tile (%u, %u)", tile_real_x, tile_real_y);
for(uint32 chy = 0; chy < 16; chy++)
{
for(uint32 chx = 0; chx < 16; chx++)
@ -402,6 +557,7 @@ void SceneWorld::UpdateTerrain(void)
}
}
// create doodads
logdebug("Loading %u doodads for tile (%u, %u)", maptile->GetDoodadCount(), tile_real_x, tile_real_y);
for(uint32 i = 0; i < maptile->GetDoodadCount(); i++)
{
Doodad *d = maptile->GetDoodad(i);
@ -446,7 +602,7 @@ void SceneWorld::UpdateTerrain(void)
}
else
{
logerror("SceneWorld: MapTile (%u, %u) not loaded, can't apply heightmap!", mapmgr->GetGridX()+tilex, mapmgr->GetGridY()+tiley);
logerror("SceneWorld: MapTile (%u, %u) not loaded!", tile_real_x, tile_real_y);
}
}
}
@ -523,7 +679,7 @@ WorldPosition SceneWorld::GetWorldPosition(void)
{
// TODO: later do not use CAMERA, but CHARACTER position, as soon as camera is changed from 1st to 3rd person view
// and floating around character in the middle
return IrrToWP(camera->getPosition(), IRR_TO_O(DEG_TO_RAD(camera->getHeading())));
return IrrToWP(camera->getPosition(), DEG_TO_RAD(camera->getHeading()));
}
video::SColor SceneWorld::GetBackgroundColor(void)
@ -531,5 +687,10 @@ video::SColor SceneWorld::GetBackgroundColor(void)
return envBasicColor;
}
void SceneWorld::_CalcXYMoveVect(float o)
{
xyCharMovement.X = cos(o);
xyCharMovement.Y = sin(o);
}

View File

@ -250,7 +250,8 @@ void PseuInstance::Run(void)
}
// fastquit is defined if we clicked [X] (on windows)
if(_fastquit)
// If softquit is set, do not terminate forcefully, but shut it down instead
if(_fastquit && !_conf->softquit)
{
log("Aborting Instance...");
return;
@ -265,6 +266,13 @@ void PseuInstance::Run(void)
//...
}
if(GetScripts()->ScriptExists("_onexit"))
{
CmdSet Set;
Set.arg[0] = DefScriptTools::toString(_error);
GetScripts()->RunScript("_onexit",&Set);
}
if(GetConf()->exitonerror == false && _error)
{
log("Exiting on error is disabled, PseuWoW is now IDLE");
@ -468,6 +476,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
useMaps=(bool)atoi(v.Get("USEMAPS").c_str());
skipaddonchat=(bool)atoi(v.Get("SKIPADDONCHAT").c_str());
dumpPackets=(uint8)atoi(v.Get("DUMPPACKETS").c_str());
softquit=(bool)atoi(v.Get("SOFTQUIT").c_str());
// clientversion is a bit more complicated to add
{

View File

@ -57,6 +57,7 @@ class PseuInstanceConf
bool useMaps;
bool skipaddonchat;
uint8 dumpPackets;
bool softquit;
// gui related
bool enablegui;

View File

@ -186,20 +186,15 @@ uint32 MapMgr::GetLoadedMapsCount(void)
float MapMgr::GetZ(float x, float y)
{
return -99999.0f; // for now return lowest possible number, GetZ() will be implemented correctly later
/* GridCoordPair gcoords = GetTransformGridCoordPair(x,y);
GridCoordPair gcoords = GetTransformGridCoordPair(x,y);
MapTile *tile = _tiles->GetTile(gcoords.x,gcoords.y);
if(tile)
{
#ifdef _DEBUG
tile->DebugDumpToFile();
logdebug("DEBUG: tile dumped");
#endif
return tile->GetZ(x,y);
}
logerror("MapMgr::GetZ() called for not loaded MapTile (%u, %u) for (%f, %f)",gcoords.x,gcoords.y,x,y);
return 0;*/
return INVALID_HEIGHT;
}
std::string MapMgr::GetLoadedTilesString(void)

View File

@ -10,6 +10,7 @@ MovementMgr::MovementMgr()
_instance = NULL;
_optime = 0;
_updatetime = 0;
_moved = false;
}
MovementMgr::~MovementMgr()
@ -21,151 +22,258 @@ void MovementMgr::SetInstance(PseuInstance *inst)
_movemode = MOVEMODE_MANUAL;
_instance = inst;
_mychar = inst->GetWSession()->GetMyChar();
if(!_mychar)
{
logerror("MovementMgr: MyCharacter doesn't exist!");
// it will likely crash somewhere after outputting this message, but in case it really appears,
// we can be sure there is something absolutely not ok...
}
}
void MovementMgr::_BuildPacket(uint16 opcode)
{
WorldPacket wp(opcode,4+1+4+12); // it can be larger, if we are juming, on transport or swimming
wp << _moveFlags;
wp << (uint8)0; // unk
wp << getMSTime();
wp << _mychar->GetPosition();
WorldPacket *wp = new WorldPacket(opcode,4+1+4+12); // it can be larger, if we are jumping, on transport or swimming
*wp << _moveFlags;
*wp << (uint8)0; // unk
*wp << getMSTime();
*wp << _mychar->GetPosition();
// TODO: transport not yet handled/done
if(_moveFlags & MOVEMENTFLAG_ONTRANSPORT)
{
wp << (uint64)0; // transport guid
wp << WorldPosition(); // transport position
wp << getMSTime(); // transport time (??)
*wp << (uint64)0; // transport guid
*wp << WorldPosition(); // transport position
*wp << getMSTime(); // transport time (??)
}
// TODO: swimming not yet done
if(_moveFlags & MOVEMENTFLAG_SWIMMING)
{
wp << (float)0; // angle; 1.55=looking up, -1.55=looking down, 0=looking forward
*wp << (float)0; // angle; 1.55=looking up, -1.55=looking down, 0=looking forward
}
wp << (uint32)0; // last fall time (also used when jumping)
// TODO: jumping not yet done
*wp << (uint32)0; // last fall time (also used when jumping)
if(_moveFlags & MOVEMENTFLAG_JUMPING)
{
*wp << (float)0; //unk value, or as mangos calls it: j_unk ^^
*wp << sin(_mychar->GetO()+ (M_PI/2));
*wp << cos(_mychar->GetO()+ (M_PI/2));
*wp << _movespeed;
}
// TODO: spline not yet done
DEBUG(logdebug("Move flags: 0x%X (packet: %u bytes)",_moveFlags,wp->size()));
// send the packet, threadsafe
_instance->GetWSession()->AddSendWorldPacket(wp);
_moved = true;
_optime = getMSTime();
}
void MovementMgr::Update(bool calcpos)
void MovementMgr::Update(bool sendDirect)
{
uint32 curtime = getMSTime();
uint32 timediff = curtime - _updatetime;
_updatetime = curtime;
if(_movemode == MOVEMODE_AUTO)
WorldPosition pos = _mychar->GetPosition();
float turnspeed = _mychar->GetSpeed(MOVE_TURN) / 1000.0f * timediff;
float runspeed = _mychar->GetSpeed(MOVE_RUN) / 1000.0f * timediff;
_movespeed = runspeed; // or use walkspeed, depending on setting. for now use only runspeed
// TODO: calc other speeds as soon as implemented
/*
if(_movemode == MOVEMODE_MANUAL)
{
WorldPosition pos = _mychar->GetPosition();
float turnspeed = _mychar->GetSpeed(MOVE_TURN) / 1000.0f * timediff;
float runspeed = _mychar->GetSpeed(MOVE_RUN) / 1000.0f * timediff;
float movespeed = runspeed; // or use walkspeed, depending on setting. for now use only runspeed
// TODO: calc other speeds as soon as implemented
/*
if(_moveFlags & MOVEMENTFLAG_FORWARD)
if(_moveFlags & MOVEMENTFLAG_JUMPING)
{
pos.x += movespeed * sin(pos.o);
pos.y += movespeed * cos(pos.o);
// approx. jumping formula
_jumptime += timediff / 1000.0f;
if (_jumptime < 0.4f)
pos.z += 2.0f / 1000.0f * timediff;
if (_jumptime >= 0.4f && _jumptime < 0.8f)
{
pos.z -= 2.0f / 1000.0f * timediff;
}
if (_jumptime >= 0.8f)
{
_jumptime = 0.0f;
_moveFlags &= ~MOVEMENTFLAG_JUMPING;
}
}
if(_movemode == MOVEMODE_AUTO)
{
if(_moveFlags & MOVEMENTFLAG_FORWARD)
{
WorldPosition oldpos = pos;
pos.x += _movespeed * sin(pos.o + (M_PI/2));
pos.y -= _movespeed * cos(pos.o + (M_PI/2));
if (_instance->GetWSession()->GetWorld()->GetPosZ(pos.x,pos.y) > 5.0f + pos.z)
{
pos = oldpos;
}
}
if(_moveFlags & MOVEMENTFLAG_BACKWARD)
{
WorldPosition oldpos = pos;
pos.x -= _movespeed * sin(pos.o + (M_PI/2));
pos.y += _movespeed * cos(pos.o + (M_PI/2));
if (_instance->GetWSession()->GetWorld()->GetPosZ(pos.x,pos.y) > 5.0f + pos.z)
{
pos = oldpos;
}
}
}
// ...
if(_moveFlags & MOVEMENTFLAG_LEFT)
{
pos.o -= turnspeed;
pos.o += turnspeed;
}
if(_moveFlags & MOVEMENTFLAG_RIGHT)
{
pos.o += turnspeed;
pos.o -= turnspeed;
}
if(pos.o < 0)
pos.o += 2 * M_PI;
pos.o += float(2 * M_PI);
else if(pos.o > 2 * M_PI)
pos.o -= 2 * M_PI;
pos.o -= float(2 * M_PI);
//pos.z = _instance->GetWSession()->GetWorld()->GetPosZ(pos.x,pos.y);
pos.z = _instance->GetWSession()->GetWorld()->GetPosZ(pos.x,pos.y);
*/
// ^ It should look like this later on, but its not finished, and formulas are not tested.
// see it as some future plans that need a lot of finetuning ;)
}
if(_movemode == MOVEMODE_AUTO)
{
_mychar->SetPosition(pos);
}
}*/
// if we are moving, and 500ms have passed, send an heartbeat packet
if( (_moveFlags & MOVEMENTFLAG_ANY_MOVE) && _optime + MOVE_HEARTBEAT_DELAY < getMSTime())
// if we are moving, and 500ms have passed, send an heartbeat packet. just in case 500ms have passed but the packet is sent by another function, do not send here
if( !sendDirect && (_moveFlags & MOVEMENTFLAG_ANY_MOVE) && _optime + MOVE_HEARTBEAT_DELAY < getMSTime())
{
_BuildPacket(MSG_MOVE_HEARTBEAT);
}
// TODO: apply gravity, handle falling, swimming, etc.
}
// stops
void MovementMgr::MoveStop(void)
{
_moveFlags &= ~(MOVEMENTFLAG_ANY_MOVE);
Update(false);
if(!(_moveFlags & (MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD)))
return;
_moveFlags &= ~(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD | MOVEMENTFLAG_WALK);
Update(true);
_BuildPacket(MSG_MOVE_STOP);
}
void MovementMgr::MoveStartForward(void)
{
if(_moveFlags & MOVEMENTFLAG_FORWARD)
return;
_moveFlags |= MOVEMENTFLAG_FORWARD;
_moveFlags &= ~MOVEMENTFLAG_BACKWARD;
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_START_FORWARD);
}
void MovementMgr::MoveStartBackward(void)
{
_moveFlags |= MOVEMENTFLAG_BACKWARD;
if(_moveFlags & MOVEMENTFLAG_BACKWARD)
return;
_moveFlags |= (MOVEMENTFLAG_BACKWARD | MOVEMENTFLAG_WALK); // backward walk is always slow; flag must be set, otherwise causing weird movement in other client
_moveFlags &= ~MOVEMENTFLAG_FORWARD;
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_START_BACKWARD);
}
void MovementMgr::MoveStartStrafeLeft(void)
{
if(_moveFlags & MOVEMENTFLAG_STRAFE_LEFT)
return;
_moveFlags |= MOVEMENTFLAG_STRAFE_LEFT;
_moveFlags &= ~MOVEMENTFLAG_STRAFE_RIGHT;
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_START_STRAFE_LEFT);
}
void MovementMgr::MoveStartStrafeRight(void)
{
if(_moveFlags & MOVEMENTFLAG_STRAFE_RIGHT)
return;
_moveFlags |= MOVEMENTFLAG_STRAFE_RIGHT;
_moveFlags &= ~MOVEMENTFLAG_STRAFE_LEFT;
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_START_STRAFE_RIGHT);
}
void MovementMgr::MoveStopStrafe(void)
{
if(!(_moveFlags & (MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_STRAFE_LEFT)))
return;
_moveFlags &= ~(MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_STRAFE_LEFT);
Update(true);
_BuildPacket(MSG_MOVE_START_STRAFE_RIGHT);
}
void MovementMgr::MoveStartTurnLeft(void)
{
if(_moveFlags & MOVEMENTFLAG_LEFT)
return;
_moveFlags |= MOVEMENTFLAG_LEFT;
_moveFlags &= ~MOVEMENTFLAG_RIGHT;
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_START_TURN_LEFT);
}
void MovementMgr::MoveStartTurnRight(void)
{
if(_moveFlags & MOVEMENTFLAG_RIGHT)
return;
_moveFlags |= MOVEMENTFLAG_RIGHT;
_moveFlags &= ~MOVEMENTFLAG_LEFT;
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_START_TURN_RIGHT);
}
void MovementMgr::MoveStopTurn(void)
{
if(!(_moveFlags & (MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT)))
return;
_moveFlags &= ~(MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
Update(false);
Update(true);
_BuildPacket(MSG_MOVE_STOP_TURN);
}
void MovementMgr::MoveSetFacing(float o)
void MovementMgr::MoveSetFacing(void)
{
_mychar->SetPosition(_mychar->GetX(), _mychar->GetY(), _mychar->GetZ(), o);
Update(true);
_BuildPacket(MSG_MOVE_SET_FACING);
}
void MovementMgr::MoveJump(void)
{
if(!(_moveFlags & (MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING)))
return;
_moveFlags |= MOVEMENTFLAG_JUMPING;
Update(true);
_BuildPacket(MSG_MOVE_JUMP);
}
bool MovementMgr::IsMoving(void)
{
return _moveFlags & MOVEMENTFLAG_ANY_MOVE;
}
bool MovementMgr::IsTurning(void)
{
return _moveFlags & (MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
}
bool MovementMgr::IsWalking(void)
{
return _moveFlags & (MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
}
bool MovementMgr::IsStrafing(void)
{
return _moveFlags & (MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
}

View File

@ -19,8 +19,8 @@ enum MovementFlagsEx
enum MoveModes
{
MOVEMODE_AUTO, // CPU controlling movement, MyCharacter must be updated
MOVEMODE_MANUAL, // user controlling movement, MyCharacter is updated by the GUI already
MOVEMODE_AUTO, // CPU controlling movement, MyCharacter must be updated by MovementMgr
MOVEMODE_MANUAL, // user controlling movement, MyCharacter must be updated by the GUI
};
class PseuInstance;
@ -34,17 +34,30 @@ public:
~MovementMgr();
void SetInstance(PseuInstance*);
inline void SetMoveMode(uint8 mode) { _movemode = mode; }
inline uint8 GetMoveMode(void) { return _movemode; }
void Update(bool);
void MoveStartForward(void);
void MoveStartBackward(void);
void MoveStop(void);
void MoveStartStrafeLeft(void);
void MoveStartStrafeRight(void);
void MoveStopStrafe(void);
void MoveStartTurnLeft(void);
void MoveStartTurnRight(void);
void MoveStopTurn(void);
void MoveFallLand(void);
void MoveSetFacing(float);
void MoveSetFacing(void);
void MoveJump(void);
//bool IsJumping(void);
inline bool GetMoveFlags(void) { return _moveFlags; }
inline bool HasMoveFlag(uint32 flag) { return _moveFlags & flag; }
bool IsMoved(void) { bool m = _moved; _moved = false; return m; } // true if the character moved since last call
bool IsMoving(void); // any move?
bool IsTurning(void); // spinning around?
bool IsWalking(void); // walking straight forward/backward?
bool IsStrafing(void); // strafing left/right?
private:
void _BuildPacket(uint16);
@ -54,7 +67,10 @@ private:
uint32 _updatetime; // timeMS of last update cycle
uint32 _optime; // timeMS when last opcode was sent
uint8 _movemode; // automatic or manual
float _movespeed; // current xy movement speed
float _jumptime;
UnitMoveType _movetype; // index used for speed selection
bool _moved;
};

View File

@ -125,6 +125,7 @@ public:
inline void SetPosition(WorldPosition& wp) { _wpos = wp; }
inline void SetPosition(WorldPosition& wp, uint16 mapid) { SetPosition(wp); _m = mapid; }
inline WorldPosition GetPosition(void) {return _wpos; }
inline WorldPosition *GetPositionPtr(void) {return &_wpos; }
inline float GetX(void) { return _wpos.x; }
inline float GetY(void) { return _wpos.y; }
inline float GetZ(void) { return _wpos.z; }

View File

@ -2,14 +2,19 @@
#include "MapMgr.h"
#include "WorldSession.h"
#include "World.h"
#include "MovementMgr.h"
World::World(WorldSession *s)
{
_session = s;
_mapId = -1;
_mapmgr = NULL;
_movemgr = NULL;
if(_session->GetInstance()->GetConf()->useMaps)
{
_mapmgr = new MapMgr();
}
}
World::~World()
@ -39,6 +44,10 @@ void World::Update(void)
{
_mapmgr->Update(_x,_y,_mapId);
}
if(_movemgr)
{
_movemgr->Update(false);
}
// some debug code for testing...
/*if(_mapmgr && _x != _lastx || _y != _lasty)
@ -71,3 +80,10 @@ float World::GetPosZ(float x, float y)
logdebug("WORLD: GetPosZ() called, but no MapMgr exists (do you really use maps?)");
return 0;
}
// must be called after MyCharacter is created
void World::CreateMoveMgr(void)
{
_movemgr = new MovementMgr();
_movemgr->SetInstance(_session->GetInstance());
}

View File

@ -3,6 +3,7 @@
class WorldSession;
class MapMgr;
class MovementMgr;
struct WorldPosition
{
@ -39,6 +40,8 @@ public:
void UpdatePos(float,float);
float GetPosZ(float x, float y);
inline MapMgr *GetMapMgr(void) { return _mapmgr; }
inline MovementMgr *GetMoveMgr(void) { return _movemgr; }
void CreateMoveMgr(void);
private:
WorldSession *_session;
@ -47,6 +50,8 @@ private:
float _x,_y;
float _lastx,_lasty;
MovementMgr *_movemgr;
};
#endif

View File

@ -362,7 +362,13 @@ void WorldSession::AddSendWorldPacket(WorldPacket *pkt)
{
sendPktQueue.add(pkt);
}
void WorldSession::AddSendWorldPacket(WorldPacket& pkt)
{
WorldPacket *wp = new WorldPacket(pkt.GetOpcode(),pkt.size());
if(pkt.size())
wp->append(pkt.contents(),pkt.size());
sendPktQueue.add(wp);
}
void WorldSession::SetTarget(uint64 guid)
{
@ -1254,7 +1260,7 @@ void WorldSession::_HandleLoginVerifyWorldOpcode(WorldPacket& recvPacket)
// update the world as soon as the server confirmed that we are where we are.
_world->UpdatePos(x,y,m);
_world->Update();
//_world->CreateMoveMgr();
_world->CreateMoveMgr();
// temp. solution to test terrain rendering
if(PseuGUI *gui = GetInstance()->GetGUI())

View File

@ -61,6 +61,7 @@ public:
void SetMustDie(void);
void SendWorldPacket(WorldPacket&);
void AddSendWorldPacket(WorldPacket *pkt);
void AddSendWorldPacket(WorldPacket& pkt);
inline bool InWorld(void) { return _logged; }
inline uint32 GetLagMS(void) { return _lag_ms; }

View File

@ -117,12 +117,10 @@ void MapTileStorage::_DebugDump(void)
}
// get approx Z position for world position (x,y).
// TODO: use inner vertices also
// TODO: interpolate values instead of choosing closest vertex
// formula taken from BoogieBot, thx!
/*float MapTile::GetZ(float x, float y)
float MapTile::GetZ(float x, float y)
{
float bx,by;
float real_z;
bx = _chunks[0].basex; // world base coords of tile
by = _chunks[0].basey;
uint32 chx = (uint32)fabs((bx - x) / CHUNKSIZE); // get chunk id for given coords
@ -131,22 +129,29 @@ void MapTileStorage::_DebugDump(void)
{
logerror("MapTile::GetZ() wrong chunk indexes (%d, %d) for (%f, %f)",chx,chy,x,y);
logerror(" - These coords are NOT on this tile!");
return 0;
return INVALID_HEIGHT;
}
MapChunk& ch = _chunks[chy*16 + chx];
MapChunk& ch = _chunks[chx*16 + chy];
uint32 vx,vy; // get vertex position (0,0) ... (8,8);
vx = (uint32)floor((fabs(ch.basex - x) / UNITSIZE) + 0.5f);
vy = (uint32)floor((fabs(ch.basey - y) / UNITSIZE) + 0.5f);
if(vx > 8 || vy > 8)
vy = (uint32)floor((fabs(ch.basey - y) / (CHUNKSIZE/16.0f)) + 0.5f);
if (vy % 2 == 0)
{
logerror("MapTile::GetZ() wrong vertex indexes (%d, %d) for chunk (%d, %d) for (%f, %f)",vx,vy,chx,chy,x,y);
return 0;
vx = (uint32)floor((fabs(ch.basex - x) / (CHUNKSIZE/8.0f)) + 0.5f);
real_z = ch.hmap_rough[vx*9 + (vy/2)] + ch.baseheight;
}
else if (vy % 2 != 0)
{
vx = (uint32)floor((fabs(ch.basex - x) / (CHUNKSIZE/7.0f)) ); //edit: removed + 0.5f
real_z = ch.hmap_fine[vx*8 + ((vy-1)/2)] + ch.baseheight;
}
if(vx > 8 || vy > 17)
{
logerror("MapTile::GetZ() wrong vertex indexes (%d, %d) for chunk (%d, %d) for (%f, %f) chunkpos (%f, %f) tile (%f, %f)",vx,vy,chx,chy,x,y,ch.basex,ch.basey,bx,by);
return INVALID_HEIGHT;
}
float real_z = ch.hmap_rough[vy*9 + vx] + ch.baseheight;
return real_z;
}*/
}
void MapTile::DebugDumpToFile(void)
{

View File

@ -11,6 +11,8 @@
#define UNITSIZE (CHUNKSIZE / 8.0f)
#define ZEROPOINT (32.0f * (TILESIZE))
#define INVALID_HEIGHT -99999.0f
// individual chunks of a map
class MapChunk
{