AvatarMoverProcess.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2007 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "AvatarMoverProcess.h"
00022 #include "Animation.h"
00023 
00024 #include "GUIApp.h"
00025 #include "MainActor.h"
00026 #include "GameMapGump.h"
00027 #include "Kernel.h"
00028 #include "ActorAnimProcess.h"
00029 #include "TargetedAnimProcess.h"
00030 #include "AvatarGravityProcess.h"
00031 #include "ShapeInfo.h"
00032 #include "SettingManager.h"
00033 #include "MusicProcess.h"
00034 #include "getObject.h"
00035 
00036 #include "IDataSource.h"
00037 #include "ODataSource.h"
00038 
00039 #include "SDL.h"
00040 
00041 // p_dynamic_cast stuff
00042 DEFINE_RUNTIME_CLASSTYPE_CODE(AvatarMoverProcess,Process);
00043 
00044 AvatarMoverProcess::AvatarMoverProcess() : Process()
00045 {
00046         lastframe = 0;
00047         lastAttack = 0;
00048         idleTime = 0;
00049         lastHeadShakeAnim = Animation::lookLeft;
00050         mouseButton[0].state = MBS_HANDLED | MBS_RELHANDLED;
00051         mouseButton[1].state = MBS_HANDLED | MBS_RELHANDLED;
00052         mouseButton[0].curDown = 0;
00053         mouseButton[1].curDown = 0;
00054         mouseButton[0].lastDown = 0;
00055         mouseButton[1].lastDown = 0;
00056         type = 1; // CONSTANT! (type 1 = persistent)
00057 }
00058 
00059 
00060 AvatarMoverProcess::~AvatarMoverProcess()
00061 {
00062 
00063 }
00064 
00065 bool AvatarMoverProcess::run(const uint32 framenum)
00066 {
00067         // only run once per frame
00068         if (framenum == lastframe) return false;
00069         lastframe = framenum;
00070 
00071 
00072         MainActor* avatar = getMainActor();
00073 
00074         // busy, so don't move
00075         if (Kernel::get_instance()->getNumProcesses(1, 0x00F0) > 0) {
00076                 idleTime = 0;
00077                 return false;
00078         }
00079            
00080 
00081         if (avatar->getLastAnim() == Animation::hang) {
00082                 return handleHangingMode(framenum);
00083         }
00084 
00085         // falling, so don't move
00086         if (avatar->getGravityPID() != 0) {
00087                 idleTime = 0;
00088                 return false;
00089         }
00090 
00091         bool combatRun = (avatar->getActorFlags() & Actor::ACT_COMBATRUN);
00092         if (avatar->isInCombat() && !combatRun)
00093                 return handleCombatMode(framenum);
00094         else
00095                 return handleNormalMode(framenum);
00096 }
00097 
00098 bool AvatarMoverProcess::handleHangingMode(const uint32 /*framenum*/)
00099 {
00100         GUIApp* guiapp = GUIApp::get_instance();
00101         MainActor* avatar = getMainActor();
00102         uint32 now = SDL_GetTicks();
00103         bool stasis = guiapp->isAvatarInStasis();
00104 
00105         idleTime = 0;
00106 
00107         if (stasis) return false;
00108 
00109         bool m0clicked = false;
00110         bool m1clicked = false;
00111         if (!(mouseButton[0].state & MBS_HANDLED) &&
00112                 now - mouseButton[0].curDown > DOUBLE_CLICK_TIMEOUT)
00113         {
00114                 m0clicked = true;
00115                 mouseButton[0].state |= MBS_HANDLED;
00116         }
00117         if (!(mouseButton[1].state & MBS_HANDLED) &&
00118                 now - mouseButton[1].curDown > DOUBLE_CLICK_TIMEOUT)
00119         {
00120                 m1clicked = true;
00121                 mouseButton[1].state |= MBS_HANDLED;
00122         }
00123         if (!(mouseButton[0].state & MBS_RELHANDLED))
00124                 mouseButton[0].state |= MBS_RELHANDLED;
00125         if (!(mouseButton[1].state & MBS_RELHANDLED))
00126                 mouseButton[1].state |= MBS_RELHANDLED;
00127 
00128 
00129         // if left mouse is down, try to climb up
00130 
00131         if ((mouseButton[0].state & MBS_DOWN) &&
00132                 (!(mouseButton[0].state & MBS_HANDLED) || m0clicked))
00133         {
00134                 mouseButton[0].state |= MBS_HANDLED;
00135                 mouseButton[0].lastDown = 0;
00136 
00137                 if (avatar->tryAnim(Animation::climb40, 8) == Animation::SUCCESS) {
00138                         avatar->ensureGravityProcess()->terminate();
00139                         waitFor(avatar->doAnim(Animation::climb40, 8));
00140                 }
00141         }
00142 
00143         return false;
00144 }
00145 
00146 bool AvatarMoverProcess::handleCombatMode(const uint32 framenum)
00147 {
00148         GUIApp* guiapp = GUIApp::get_instance();
00149         MainActor* avatar = getMainActor();
00150         Animation::Sequence lastanim = avatar->getLastAnim();
00151         Animation::Sequence nextanim = Animation::walk;
00152         sint32 direction = avatar->getDir();
00153         uint32 now = SDL_GetTicks();
00154         bool stasis = guiapp->isAvatarInStasis();
00155 
00156         int mx, my;
00157         guiapp->getMouseCoords(mx, my);
00158         unsigned int mouselength = guiapp->getMouseLength(mx,my);
00159 
00160         // adjust to world direction
00161         sint32 mousedir = (guiapp->getMouseDirection(mx,my)+7)%8;
00162 
00163         // never idle when in combat
00164         idleTime = 0;
00165 
00166         // If Avatar has fallen down, stand up.
00167         if (lastanim == Animation::die || lastanim == Animation::fallBackwards) {
00168                 if (!stasis)
00169                         waitFor(avatar->doAnim(Animation::standUp, mousedir));
00170                 return false;
00171         }
00172 
00173         // if we were blocking, and no longer holding the mouse, stop
00174         if (lastanim == Animation::startBlock &&
00175                 !(mouseButton[0].state & MBS_DOWN))
00176         {
00177 //              pout << "AvatarMover: combat stop blocking" << std::endl;
00178                 waitFor(avatar->doAnim(Animation::stopBlock, direction));
00179                 return false;
00180         }
00181 
00182         // can't do any new actions if in stasis
00183         if (stasis)
00184                 return false;
00185 
00186         bool m0clicked = false;
00187         bool m1clicked = false;
00188 
00189         if (!(mouseButton[0].state & MBS_HANDLED) &&
00190                 now - mouseButton[0].curDown > DOUBLE_CLICK_TIMEOUT)
00191         {
00192                 m0clicked = true;
00193                 mouseButton[0].state |= MBS_HANDLED;
00194         }
00195 
00196         if (!(mouseButton[1].state & MBS_HANDLED) &&
00197                 now - mouseButton[1].curDown > DOUBLE_CLICK_TIMEOUT)
00198         {
00199                 m1clicked = true;
00200                 mouseButton[1].state |= MBS_HANDLED;
00201         }
00202 
00203         if (!(mouseButton[0].state & MBS_RELHANDLED))
00204                 mouseButton[0].state |= MBS_RELHANDLED;
00205 
00206         if (!(mouseButton[1].state & MBS_RELHANDLED))
00207                 mouseButton[1].state |= MBS_RELHANDLED;
00208 
00209         if ((mouseButton[0].state & MBS_DOWN) &&
00210                 (mouseButton[0].state & MBS_HANDLED) && mouseButton[0].lastDown > 0)
00211         {
00212                 // left click-and-hold = block
00213                 if (lastanim == Animation::startBlock)
00214                         return false;
00215 
00216 //              pout << "AvatarMover: combat block" << std::endl;
00217 
00218                 if (checkTurn(mousedir, false)) return false;
00219 
00220                 waitFor(avatar->doAnim(Animation::startBlock, mousedir));
00221                 return false;
00222         }
00223 
00224         if ((mouseButton[0].state & MBS_DOWN) &&
00225                 !(mouseButton[0].state & MBS_HANDLED) &&
00226                 mouseButton[0].curDown-mouseButton[0].lastDown <= DOUBLE_CLICK_TIMEOUT)
00227         {
00228                 mouseButton[0].state |= MBS_HANDLED;
00229                 mouseButton[0].lastDown = 0;
00230 
00231                 if (canAttack()) {
00232                         // double left click = attack
00233 //                      pout << "AvatarMover: combat attack" << std::endl;
00234 
00235                         if (checkTurn(mousedir, true)) return false;
00236 
00237                         waitFor(avatar->doAnim(Animation::attack, mousedir));
00238                         lastAttack = framenum;
00239 
00240                         // attacking gives str/dex
00241                         avatar->accumulateStr(1+(std::rand()%2));
00242                         avatar->accumulateDex(2+(std::rand()%2));
00243                 }
00244 
00245                 return false;
00246         }
00247 
00248         if ((mouseButton[1].state & MBS_DOWN) &&
00249                 !(mouseButton[1].state & MBS_HANDLED) &&
00250                 mouseButton[1].curDown-mouseButton[1].lastDown <= DOUBLE_CLICK_TIMEOUT)
00251         {
00252                 mouseButton[1].state |= MBS_HANDLED;
00253                 mouseButton[1].lastDown = 0;
00254 
00255                 Gump* desktopgump = GUIApp::get_instance()->getDesktopGump();
00256                 if (desktopgump->TraceObjId(mx,my) == 1) {
00257                         // double right click on avatar = toggle combat mode
00258                         avatar->toggleInCombat();
00259                         waitFor(avatar->doAnim(Animation::unreadyWeapon, direction));
00260                         return false;
00261                 }
00262 
00263                 if (canAttack()) {
00264                         // double right click = kick
00265 //                      pout << "AvatarMover: combat kick" << std::endl;
00266 
00267                         if (checkTurn(mousedir, false)) return false;
00268                         
00269                         waitFor(avatar->doAnim(Animation::kick, mousedir));
00270                         lastAttack = framenum;
00271 
00272                         // kicking gives str/dex
00273                         avatar->accumulateStr(1+(std::rand()%2));
00274                         avatar->accumulateDex(2+(std::rand()%2));
00275                 }
00276 
00277                 return false;
00278         }
00279 
00280         if ((mouseButton[1].state & MBS_DOWN) &&
00281                 (mouseButton[1].state & MBS_HANDLED) && mouseButton[1].lastDown > 0)
00282         {
00283                 // right mouse button is down long enough to act on it
00284                 // if facing right direction, walk
00286 
00287                 if (checkTurn(mousedir, true)) return false;
00288 
00289                 sint32 nextdir = mousedir;
00290 
00291                 if (lastanim == Animation::run) {
00292                         // want to run while in combat mode?
00293                         // first sheath weapon
00294                         nextanim = Animation::readyWeapon;
00295                 } else if (abs(direction - mousedir) == 4) {
00296                         nextanim = Animation::retreat;
00297                         nextdir = direction;
00298                 } else
00299                         nextanim = Animation::advance;
00300 
00301                 if (mouselength == 2)
00302                 {
00303                         // Take a step before running
00304                         nextanim = Animation::walk;
00305                         avatar->setActorFlag(Actor::ACT_COMBATRUN);
00306                         avatar->toggleInCombat();
00307                         MusicProcess::get_instance()->playCombatMusic(110); // CONSTANT!!
00308                 }
00309 
00310                 nextanim = Animation::checkWeapon(nextanim, lastanim);
00311                 waitFor(avatar->doAnim(nextanim, nextdir));
00312                 return false;
00313         }
00314 
00315         // if clicked, turn in mouse direction
00316         if (m0clicked || m1clicked)
00317                 if (checkTurn(mousedir, false)) return false;
00318 
00319         // not doing anything in particular? stand
00320         // TODO: make sure falling works properly.
00321         if (lastanim != Animation::combatStand) {
00322                 nextanim = Animation::combatStand;
00323                 nextanim = Animation::checkWeapon(nextanim, lastanim);
00324                 waitFor(avatar->doAnim(nextanim, direction));
00325         }
00326 
00327         return false;
00328 }
00329 
00330 bool AvatarMoverProcess::handleNormalMode(const uint32 /*framenum*/)
00331 {
00332         GUIApp* guiapp = GUIApp::get_instance();
00333         MainActor* avatar = getMainActor();
00334         Animation::Sequence lastanim = avatar->getLastAnim();
00335         Animation::Sequence nextanim = Animation::walk;
00336         sint32 direction = avatar->getDir();
00337         uint32 now = SDL_GetTicks();
00338         bool stasis = guiapp->isAvatarInStasis();
00339         bool combatRun = (avatar->getActorFlags() & Actor::ACT_COMBATRUN);
00340 
00341         int mx, my;
00342         guiapp->getMouseCoords(mx, my);
00343         unsigned int mouselength = guiapp->getMouseLength(mx,my);
00344 
00345         // adjust to world direction
00346         sint32 mousedir = (guiapp->getMouseDirection(mx,my)+7)%8;
00347 
00348         // Store current idle time. (Also see end of function.)
00349         sint32 currentIdleTime = idleTime;
00350         idleTime = 0;
00351 
00352         // User toggled combat while in combatRun
00353         if (avatar->isInCombat())
00354         {
00355                 avatar->clearActorFlag(Actor::ACT_COMBATRUN);
00356                 avatar->toggleInCombat();
00357         }
00358 
00359         // If Avatar has fallen down, stand up.
00360         if (lastanim == Animation::die || lastanim == Animation::fallBackwards) {
00361                 if (!stasis) {
00362 //                      pout << "AvatarMover: standing up" << std::endl;
00363                         waitFor(avatar->doAnim(Animation::standUp, direction));
00364                 }
00365                 return false;
00366         }
00367 
00368         // If still in combat stance, sheathe weapon
00369         if (!stasis && Animation::isCombatAnim(lastanim)) {
00370 //              pout << "AvatarMover: sheathing weapon" << std::endl;
00371 
00372                 ProcId anim1 = avatar->doAnim(Animation::unreadyWeapon, direction);
00373                 ProcId anim2 = avatar->doAnim(Animation::stand, direction);
00374                 Process* anim2p = Kernel::get_instance()->getProcess(anim2);
00375                 anim2p->waitFor(anim1);
00376                 waitFor(anim2);
00377 
00378                 return false;
00379         }
00380 
00381         bool m0clicked = false;
00382         bool m1clicked = false;
00383 
00384     // check mouse state to see what needs to be done
00385         if (!(mouseButton[0].state & MBS_HANDLED) &&
00386                 now - mouseButton[0].curDown > DOUBLE_CLICK_TIMEOUT)
00387         {
00388                 m0clicked = true;
00389                 mouseButton[0].state |= MBS_HANDLED;
00390         }
00391 
00392         if (!(mouseButton[1].state & MBS_HANDLED) &&
00393                 now - mouseButton[1].curDown > DOUBLE_CLICK_TIMEOUT)
00394         {
00395                 m1clicked = true;
00396                 mouseButton[1].state |= MBS_HANDLED;
00397         }
00398 
00399         // see if mouse was just released
00400         if (!(mouseButton[0].state & MBS_RELHANDLED))
00401                 mouseButton[0].state |= MBS_RELHANDLED; // don't care about left
00402 
00403         if (!(mouseButton[1].state & MBS_RELHANDLED)) {
00404                 mouseButton[1].state |= MBS_RELHANDLED;
00405 
00406                 // if we were running in combat mode, slow to a walk, draw weapon
00407                 // (even in stasis)
00408                 if (combatRun)
00409                 {
00410                         MainActor* avatar = getMainActor();
00411                         avatar->clearActorFlag(Actor::ACT_COMBATRUN);
00412                         avatar->toggleInCombat();
00413                         ProcId walkpid = avatar->doAnim(Animation::walk, direction);
00414                         ProcId drawpid = avatar->doAnim(Animation::readyWeapon, direction);
00415                         Process* drawproc = Kernel::get_instance()->getProcess(drawpid);
00416                         drawproc->waitFor(walkpid);
00417                         waitFor(drawpid);
00418                         return false;
00419                 }
00420 
00421                 // if we were running, slow to a walk before stopping
00422                 // (even in stasis)
00423                 if (lastanim == Animation::run) {
00424                         ProcId walkpid = avatar->doAnim(Animation::walk, direction);
00425                         ProcId standpid = avatar->doAnim(Animation::stand, direction);
00426                         Process* standproc = Kernel::get_instance()->getProcess(standpid);
00427                         standproc->waitFor(walkpid);
00428                         waitFor(standpid);
00429                         return false;
00430                 }
00431 
00432                 // TODO: if we were hanging, fall
00433 
00434                 // otherwise, stand
00435                 if (!stasis)
00436                         waitFor(avatar->doAnim(Animation::stand, direction));
00437                 return false;           
00438         }
00439 
00440         // can't do any new actions if in stasis
00441         if (stasis)
00442                 return false;
00443 
00444         // both mouse buttons down
00445         if (!(mouseButton[0].state & MBS_HANDLED) &&
00446                 !(mouseButton[1].state & MBS_HANDLED))
00447         {
00448                 // notice these are all unsigned.
00449                 uint32 down = mouseButton[1].curDown;
00450                 if (mouseButton[0].curDown < down)
00451                 {
00452                         down = down - mouseButton[0].curDown;
00453                 }
00454                 else
00455                 {
00456                         down = mouseButton[0].curDown - down;
00457                 }
00458                 
00459                 if (down < DOUBLE_CLICK_TIMEOUT)
00460                 {
00461                         mouseButton[0].state |= MBS_HANDLED;
00462                         mouseButton[1].state |= MBS_HANDLED;
00463                         // We got a left mouse down.
00464                         // Note that this automatically means right was down too.
00465 
00466                         if (checkTurn(mousedir, false)) return false;
00467 
00468                         nextanim = Animation::jumpUp;
00469                         if (mouselength > 0) {
00470                                 nextanim = Animation::jump;
00471                         }
00472                         // check if there's something we can climb up onto here
00473 
00474                         Animation::Sequence climbanim = Animation::climb72;
00475                         while (climbanim >= Animation::climb16)
00476                         {
00477                                 if (avatar->tryAnim(climbanim, direction) == 
00478                                         Animation::SUCCESS)
00479                                 {
00480                                         nextanim = climbanim;
00481                                 }
00482                                 climbanim = static_cast<Animation::Sequence>(climbanim-1);
00483                         }
00484 
00485                         if (nextanim == Animation::jump || nextanim == Animation::jumpUp)
00486                         {
00487                                 jump(nextanim, direction);
00488                                 return false;
00489                         }
00490 
00491                         // climbing gives str/dex
00492                         avatar->accumulateStr(2+nextanim-Animation::climb16);
00493                         avatar->accumulateDex(2*(2+nextanim-Animation::climb16));
00494 
00495                         nextanim = Animation::checkWeapon(nextanim, lastanim);
00496                         waitFor(avatar->doAnim(nextanim, direction));
00497                         return false;
00498                 }
00499         }
00500 
00501         if ((!(mouseButton[0].state & MBS_HANDLED) || m0clicked) &&
00502                 (mouseButton[1].state & MBS_DOWN))
00503         {
00504                 mouseButton[0].state |= MBS_HANDLED;
00505                 // We got a left mouse down.
00506                 // Note that this automatically means right was down at the time too.
00507 
00508                 if (checkTurn(mousedir, false)) return false;
00509 
00510                 nextanim = Animation::jumpUp;
00511 
00512                 // check if we need to do a running jump
00513                 if (lastanim == Animation::run ||
00514                         lastanim == Animation::runningJump) {
00515                         pout << "AvatarMover: running jump" << std::endl;
00516                         jump(Animation::runningJump, direction);
00517                         return false;
00518                 } else if (mouselength > 0) {
00519                         pout << "AvatarMover: jump" << std::endl;
00520                         jump(Animation::jump, direction);
00521                         return false;
00522                 }
00523                 nextanim = Animation::checkWeapon(nextanim, lastanim);
00524                 waitFor(avatar->doAnim(nextanim, direction));
00525                 return false;
00526 
00527                 // CHECKME: check what needs to happen when keeping left pressed
00528         }
00529 
00530         if ((mouseButton[1].state & MBS_DOWN) &&
00531                 !(mouseButton[1].state & MBS_HANDLED) &&
00532                 mouseButton[1].curDown-mouseButton[1].lastDown <= DOUBLE_CLICK_TIMEOUT)
00533         {
00534                 Gump* desktopgump = GUIApp::get_instance()->getDesktopGump();
00535                 if (desktopgump->TraceObjId(mx,my) == 1) {
00536                         // double right click on avatar = toggle combat mode
00537                         mouseButton[1].state |= MBS_HANDLED;
00538                         mouseButton[1].lastDown = 0;
00539 
00540                         avatar->toggleInCombat();
00541                         waitFor(avatar->doAnim(Animation::readyWeapon, direction));
00542                         return false;
00543                 }
00544         }
00545 
00546         if ((mouseButton[1].state & MBS_DOWN) &&
00547                 (mouseButton[1].state & MBS_HANDLED))
00548         {
00549                 // right mouse button is down long enough to act on it
00550                 // if facing right direction, walk
00551 
00552                 nextanim = Animation::step;
00553 
00554                 if (mouselength == 1)
00555                         nextanim = Animation::walk;
00556 
00557                 if (mouselength == 2)
00558                 {
00559                         if (lastanim == Animation::run
00560                                 || lastanim == Animation::runningJump
00561                                 || lastanim == Animation::walk)
00562                                 nextanim = Animation::run;
00563                         else                            
00564                                 nextanim = Animation::walk;
00565                 }
00566 
00567                 step(nextanim, mousedir);
00568                 return false;
00569         }
00570 
00571         if (m1clicked)
00572                 if (checkTurn(mousedir, false)) return true;
00573 
00574         // doing another animation?
00575         if (Kernel::get_instance()->getNumProcesses(1, 0x00F0))
00576                 return false;
00577 
00578         // idle
00579         idleTime = currentIdleTime + 1;
00580 
00581         // currently shaking head?
00582         if (lastanim == Animation::lookLeft || lastanim == Animation::lookRight) {
00583                 if ((std::rand() % 1500) + 30 < idleTime) {
00584                         lastHeadShakeAnim = lastanim;
00585                         waitFor(avatar->doAnim(Animation::stand, direction));
00586                         idleTime = 0;
00587                         return false;
00588                 }
00589         } else {
00590                 if ((std::rand() % 3000) + 150 < idleTime) {
00591                         if (std::rand() % 5 == 0)
00592                                 nextanim = lastHeadShakeAnim;
00593                         else
00594                                 if (lastHeadShakeAnim == Animation::lookLeft)
00595                                         nextanim = Animation::lookRight;
00596                                 else
00597                                         nextanim = Animation::lookLeft;
00598                         waitFor(avatar->doAnim(nextanim, direction));
00599                         idleTime = 0;
00600                 }
00601         }
00602 
00603         return false;
00604 }
00605 
00606 void AvatarMoverProcess::step(Animation::Sequence action, int direction,
00607                                                           bool adjusted)
00608 {
00609         assert(action == Animation::step || action == Animation::walk ||
00610                    action == Animation::run);
00611 
00612         MainActor* avatar = getMainActor();
00613         Animation::Sequence lastanim = avatar->getLastAnim();
00614 
00615         Animation::Result res = avatar->tryAnim(action, direction);
00616 
00617         int stepdir = direction;
00618 
00619         if (res == Animation::FAILURE ||
00620                 (action == Animation::step && res == Animation::END_OFF_LAND))
00621         {
00622                 int altdir1 = (stepdir + 1)%8;
00623                 int altdir2 = (stepdir + 7)%8;
00624 
00625                 res = avatar->tryAnim(action, altdir1);
00626                 if (res == Animation::FAILURE ||
00627                         (action == Animation::step && res == Animation::END_OFF_LAND))
00628                 {
00629                         res = avatar->tryAnim(action, altdir2);
00630                         if (res == Animation::FAILURE ||
00631                                 (action == Animation::step && res == Animation::END_OFF_LAND))
00632                         {
00633                                 // Can't walk in this direction.
00634                                 // Try to take a smaller step
00635 
00636                                 if (action == Animation::walk) {
00637                                         step(Animation::step, direction, true);
00638                                         return;
00639                                 } else if (action == Animation::run) {
00640                                         step(Animation::walk, direction, true);
00641                                         return;
00642                                 }
00643 
00644                         } else {
00645                                 stepdir = altdir2;
00646                         }
00647                 } else {
00648                         stepdir = altdir1;
00649                 }
00650 
00651 
00652         }
00653 
00654         if (action == Animation::step && res == Animation::END_OFF_LAND &&
00655                 lastanim != Animation::keepBalance && !adjusted)
00656         {
00657                 if (checkTurn(stepdir, false)) return;
00658                 waitFor(avatar->doAnim(Animation::keepBalance, stepdir));
00659                 return;
00660         }
00661 
00662         if (action == Animation::step && res == Animation::FAILURE)
00663         {
00664                 action = Animation::stand;
00665         }
00666 
00667 
00668         bool moving = (action == Animation::run || action == Animation::walk);
00669         
00670         if (checkTurn(stepdir, moving)) return;
00671         
00672         action = Animation::checkWeapon(action, lastanim);
00673         waitFor(avatar->doAnim(action, stepdir));
00674 }
00675 
00676 void AvatarMoverProcess::jump(Animation::Sequence action, int direction)
00677 {
00678         GUIApp* guiapp = GUIApp::get_instance();
00679         MainActor* avatar = getMainActor();
00680         int mx, my;
00681         guiapp->getMouseCoords(mx, my);
00682 
00683         // running jump
00684         if (action == Animation::runningJump)
00685         {
00686                 waitFor(avatar->doAnim(action, direction));
00687                 return;
00688         }
00689 
00690         // airwalk
00691         if ((avatar->getActorFlags() & Actor::ACT_AIRWALK) &&
00692                 action == Animation::jump)
00693         {
00694                 waitFor(avatar->doAnim(Animation::airwalkJump, direction));
00695                 return;
00696         }
00697 
00698         bool targeting;
00699         SettingManager::get_instance()->get("targetedjump", targeting);
00700 
00701         if (targeting) {
00702                 sint32 coords[3];
00703                 GameMapGump * gameMap = guiapp->getGameMapGump();
00704                 // We need the Gump's x/y for TraceCoordinates
00705                 gameMap->ScreenSpaceToGump(mx,my);
00706                 ObjId targetId = gameMap->TraceCoordinates(mx,my,coords);
00707                 Item * target = getItem(targetId);
00708 
00709                 sint32 ax,ay,az;
00710                 avatar->getCentre(ax,ay,az);
00711 
00712                 sint32 xrange = ax-coords[0];
00713                 if (xrange < 0) xrange = -xrange;
00714                 sint32 yrange = ay-coords[1];
00715                 if (yrange < 0) yrange = -yrange;
00716                 int maxrange = avatar->getStr() * 32;
00717         
00718                 if (target && target->getShapeInfo()->is_land() &&
00719                         xrange < maxrange && yrange < maxrange)
00720                 {       // Original also only lets you jump at the Z_FACE
00721                         Process *p = new TargetedAnimProcess(avatar, Animation::jumpUp,
00722                                                                                                  direction, coords);
00723                         waitFor(Kernel::get_instance()->addProcess(p));
00724                         return;
00725                 }
00726                 // invalid target or out of range
00727                 waitFor(avatar->doAnim(Animation::shakeHead, direction));
00728         } else {
00729                 waitFor(avatar->doAnim(Animation::jump, direction));
00730         }
00731 }
00732 
00733 void AvatarMoverProcess::turnToDirection(int direction)
00734 {
00735         MainActor* avatar = getMainActor();
00736         bool combatRun = (avatar->getActorFlags() & Actor::ACT_COMBATRUN);
00737         int curdir = avatar->getDir();
00738         int step;
00739         bool combat = avatar->isInCombat() && !combatRun;
00740         Animation::Sequence turnanim;
00741         Animation::Sequence standanim = Animation::stand;
00742 
00743         if ((curdir - direction + 8) % 8 < 4) {
00744                 step = -1;
00745                 turnanim = Animation::lookLeft;
00746         } else {
00747                 step = 1;
00748                 turnanim = Animation::lookRight;
00749         }
00750 
00751         if (combat) {
00752                 turnanim = Animation::combatStand;
00753                 standanim = Animation::combatStand;
00754         }
00755 
00756         ProcId prevpid = 0;
00757 
00758         for (int dir = curdir; dir != direction; ) {
00759                 ProcId animpid = avatar->doAnim(turnanim, dir);
00760 
00761                 if (prevpid) {
00762                         Process* proc = Kernel::get_instance()->getProcess(animpid);
00763                         assert(proc);
00764                         proc->waitFor(prevpid);
00765                 }
00766 
00767                 prevpid = animpid;
00768 
00769                 dir = (dir + step + 8) % 8;
00770         }
00771 
00772         ProcId animpid = avatar->doAnim(standanim, direction);
00773 
00774         if (prevpid) {
00775                 Process* proc = Kernel::get_instance()->getProcess(animpid);
00776                 assert(proc);
00777                 proc->waitFor(prevpid);
00778         }
00779         
00780         waitFor(animpid);
00781 }
00782 
00783 bool AvatarMoverProcess::checkTurn(int direction, bool moving)
00784 {
00785         MainActor* avatar = getMainActor();
00786         bool combatRun = (avatar->getActorFlags() & Actor::ACT_COMBATRUN);
00787         int curdir = avatar->getDir();
00788         bool combat = avatar->isInCombat() && !combatRun;
00789         Animation::Sequence lastanim = avatar->getLastAnim();
00790 
00791         // Note: don't need to turn if moving backward in combat stance
00792         // CHECKME: currently, first turn in the right direction
00793         if (direction != curdir && !(
00794                         combat && abs(direction - curdir) == 4))
00795         {
00796                 if (moving &&
00797                         (lastanim == Animation::walk || lastanim == Animation::run ||
00798                          lastanim == Animation::combatStand) &&
00799                         (abs(direction - curdir) + 1 % 8 <= 2))
00800                 {
00801                         // don't need to explicitly do a turn animation
00802                         return false;
00803                 }
00804 
00805                 if (moving && lastanim == Animation::run) {
00806                         // slow down to a walk first
00807                         waitFor(avatar->doAnim(Animation::walk, curdir));
00808                         return true;
00809                 }
00810 
00811                 turnToDirection(direction);
00812                 return true;
00813         }
00814 
00815         return false;
00816 }
00817 
00818 bool AvatarMoverProcess::canAttack()
00819 {
00820         MainActor* avatar = getMainActor();
00821         return (lastframe > lastAttack + (25 - avatar->getDex()));
00822 }
00823 
00824 void AvatarMoverProcess::OnMouseDown(int button, int mx, int my)
00825 {
00826         int bid = 0;
00827 
00828         switch (button) {
00829         case BUTTON_LEFT:
00830         {
00831                 bid = 0;
00832                 break;
00833         }
00834         case BUTTON_RIGHT:
00835         {
00836                 bid = 1;
00837                 break;
00838         }
00839         default:
00840                 CANT_HAPPEN_MSG("invalid MouseDown passed to AvatarMoverProcess");
00841                 break;
00842         };
00843 
00844         mouseButton[bid].lastDown = mouseButton[bid].curDown;
00845         mouseButton[bid].curDown = SDL_GetTicks();
00846         mouseButton[bid].state |= MBS_DOWN;
00847         mouseButton[bid].state &= ~MBS_HANDLED;
00848 }
00849 
00850 void AvatarMoverProcess::OnMouseUp(int button)
00851 {
00852         int bid = 0;
00853 
00854         if (button == BUTTON_LEFT) {
00855                 bid = 0;
00856         } else if (button == BUTTON_RIGHT) {
00857                 bid = 1;
00858         } else {
00859                 CANT_HAPPEN_MSG("invalid MouseUp passed to AvatarMoverProcess");
00860         }
00861 
00862         mouseButton[bid].state &= ~MBS_DOWN;
00863         mouseButton[bid].state &= ~MBS_RELHANDLED;
00864 }
00865 
00866 
00867 void AvatarMoverProcess::saveData(ODataSource* ods)
00868 {
00869         Process::saveData(ods);
00870 
00871         ods->write4(lastAttack);
00872         ods->write4(idleTime);
00873         ods->write2(static_cast<uint8>(lastHeadShakeAnim));
00874 }
00875 
00876 bool AvatarMoverProcess::loadData(IDataSource* ids, uint32 version)
00877 {
00878         if (!Process::loadData(ids, version)) return false;
00879 
00880         lastAttack = ids->read4();
00881         idleTime = ids->read4();
00882         lastHeadShakeAnim = static_cast<Animation::Sequence>(ids->read2());
00883 
00884         return true;
00885 }

Generated on Fri Jul 27 22:27:09 2007 for pentagram by  doxygen 1.4.7