Actor.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 #include "Actor.h"
00021 
00022 #include "ObjectManager.h"
00023 #include "Kernel.h"
00024 #include "UCMachine.h"
00025 #include "UCList.h"
00026 #include "World.h"
00027 #include "ActorAnimProcess.h"
00028 #include "AnimationTracker.h"
00029 #include "CurrentMap.h"
00030 #include "Direction.h"
00031 #include "GameData.h"
00032 #include "MainShapeArchive.h"
00033 #include "AnimAction.h"
00034 #include "ShapeInfo.h"
00035 #include "Pathfinder.h"
00036 #include "Animation.h"
00037 #include "DelayProcess.h"
00038 #include "ResurrectionProcess.h"
00039 #include "DestroyItemProcess.h"
00040 #include "ClearFeignDeathProcess.h"
00041 #include "PathfinderProcess.h"
00042 #include "Shape.h"
00043 #include "LoiterProcess.h"
00044 #include "CombatProcess.h"
00045 #include "AudioProcess.h"
00046 #include "SpriteProcess.h"
00047 #include "MainActor.h"
00048 #include "MusicProcess.h"
00049 #include "getObject.h"
00050 
00051 #include "ItemFactory.h"
00052 #include "LoopScript.h"
00053 #include "IDataSource.h"
00054 #include "ODataSource.h"
00055 
00056 // p_dynamic_cast stuff
00057 DEFINE_RUNTIME_CLASSTYPE_CODE(Actor,Container);
00058 
00059 Actor::Actor()
00060         : strength(0), dexterity(0), intelligence(0),
00061           hitpoints(0), mana(0), alignment(0), enemyalignment(0),
00062           lastanim(Animation::walk), animframe(0), direction(0),
00063           fallstart(0), unk0C(0), actorflags(0)
00064 {
00065 
00066 }
00067 
00068 Actor::~Actor()
00069 {
00070 
00071 }
00072 
00073 uint16 Actor::assignObjId()
00074 {
00075         if (objid == 0xFFFF)
00076                 objid = ObjectManager::get_instance()->assignActorObjId(this);
00077 
00078         std::list<Item*>::iterator iter;
00079         for (iter = contents.begin(); iter != contents.end(); ++iter) {
00080                 (*iter)->assignObjId();
00081                 (*iter)->setParent(objid);
00082         }
00083 
00084         return objid;
00085 }
00086 
00087 sint16 Actor::getMaxMana() const
00088 {
00089         return static_cast<sint16>(2 * getInt());
00090 }
00091 
00092 uint16 Actor::getMaxHP() const
00093 {
00094         return static_cast<uint16>(2 * getStr());
00095 }
00096 
00097 bool Actor::loadMonsterStats()
00098 {
00099         ShapeInfo* shapeinfo = getShapeInfo();
00100         MonsterInfo* mi = 0;
00101         if (shapeinfo) mi = shapeinfo->monsterinfo;
00102         if (!mi)
00103                 return false;
00104 
00105         uint16 hp;
00106         if (mi->max_hp <= mi->min_hp)
00107                 hp = mi->min_hp;
00108         else
00109                 hp = mi->min_hp + std::rand() % (mi->max_hp - mi->min_hp);
00110         setHP(hp);
00111         
00112         uint16 dex;
00113         if (mi->max_dex <= mi->min_dex)
00114                 dex = mi->min_dex;
00115         else
00116                 dex = mi->min_dex + std::rand() % (mi->max_dex - mi->min_dex);
00117         setDex(dex);
00118         
00119         uint8 alignment = mi->alignment;
00120         setAlignment(alignment & 0x0F);
00121         setEnemyAlignment((alignment & 0xF0) >> 4); // !! CHECKME
00122 
00123         return true;
00124 }
00125 
00126 bool Actor::giveTreasure()
00127 {
00128         MainShapeArchive* mainshapes = GameData::get_instance()->getMainShapes();
00129         ShapeInfo* shapeinfo = getShapeInfo();
00130         MonsterInfo* mi = 0;
00131         if (shapeinfo) mi = shapeinfo->monsterinfo;
00132         if (!mi)
00133                 return false;
00134 
00135         std::vector<TreasureInfo>& treasure = mi->treasure;
00136 
00137         for (unsigned int i = 0; i < treasure.size(); ++i) {
00138                 TreasureInfo& ti = treasure[i];
00139                 Item* item;
00140 
00141                 // check map
00142                 int currentmap = World::get_instance()->getCurrentMap()->getNum();
00143                 if (ti.map != 0 && ((ti.map > 0 && ti.map != currentmap) ||
00144                                                         (ti.map < 0 && -ti.map == currentmap)))
00145                 {
00146                         continue;
00147                 }
00148 
00149                 // check chance
00150                 if (ti.chance < 0.999 &&
00151                         (static_cast<double>(std::rand()) / RAND_MAX) > ti.chance)
00152                 {
00153                         continue;
00154                 }
00155 
00156                 // determine count/quantity
00157                 int count;
00158                 if (ti.mincount >= ti.maxcount)
00159                         count = ti.mincount;
00160                 else
00161                         count = ti.mincount + (std::rand() % (ti.maxcount - ti.mincount));
00162 
00163                 if (!ti.special.empty()) {
00164                         if (ti.special == "weapon") {
00165 
00166                                 // NB: this is rather biased towards weapons with low shapes...
00167                                 for (unsigned int s = 0; s < mainshapes->getCount(); ++s) {
00168                                         ShapeInfo* si = mainshapes->getShapeInfo(s);
00169                                         if (!si->weaponinfo) continue;
00170 
00171                                         int chance = si->weaponinfo->treasure_chance;
00172                                         if (!chance) continue;
00173 
00174                                         int r = std::rand() % 100;
00175 #if 0
00176                                         pout << "weapon (" << s << ") chance: " << r << "/"
00177                                                  << chance << std::endl;
00178 #endif
00179                                         if (r >= chance) continue;
00180 
00181                                         // create the weapon
00182                                         item = ItemFactory::createItem(s,
00183                                                                                                    0, // frame
00184                                                                                                    count, // quality
00185                                                                                                    Item::FLG_DISPOSABLE,//flags
00186                                                                                                    0, // npcnum,
00187                                                                                                    0, // mapnum
00188                                                                                                    0, true); // ext.flags,objid
00189                                         item->moveToContainer(this);
00190                                         item->randomGumpLocation();
00191                                         break;
00192                                 }
00193                         } else if (ti.special == "sorcfocus") {
00194                                 // CONSTANTS! (and lots of them...)
00195                                 int shape = 397;
00196                                 int frame;
00197                                 uint16 quality;
00198 
00199                                 if (std::rand() % 10 < 8)
00200                                 {
00201                                         // wand
00202                                         if (std::rand() % 10 < 4) {
00203                                                 // charged
00204                                                 frame = 0;
00205                                                 quality = 3 + (std::rand() % 4) + // charges
00206                                                         ((1 + (std::rand()%4))<<8);   // spell
00207                                         } else {
00208                                                 frame = 15;
00209                                                 quality = 0;
00210                                         }
00211 
00212                                         item = ItemFactory::createItem(shape, frame, quality,
00213                                                                                                    Item::FLG_DISPOSABLE,
00214                                                                                                    0, 0, 0, true);
00215                                         item->moveToContainer(this);
00216                                         item->randomGumpLocation();
00217                                 }
00218 
00219                                 if (std::rand() % 10 < 6)
00220                                 {
00221                                         // rod
00222                                         if (std::rand() % 10 < 2) {
00223                                                 // charged
00224                                                 frame = 3;
00225                                                 quality = 3 + (std::rand() % 4) + // charges
00226                                                         ((1 + (std::rand()%7))<<8);   // spell
00227                                         } else {
00228                                                 frame = 16;
00229                                                 quality = 0;
00230                                         }
00231 
00232                                         item = ItemFactory::createItem(shape, frame, quality,
00233                                                                                                    Item::FLG_DISPOSABLE,
00234                                                                                                    0, 0, 0, true);
00235                                         item->moveToContainer(this);
00236                                         item->randomGumpLocation();
00237                                 }
00238 
00239                                 if (std::rand() % 10 < 5)
00240                                 {
00241                                         // symbol
00242                                         if (std::rand() % 10 < 5) {
00243                                                 // charged
00244                                                 frame = 12;
00245                                                 uint8 spell = 1 + (std::rand()%11);
00246                                                 quality = spell<<8;
00247                                                 if (spell < 4) {
00248                                                         quality += 3 + (std::rand()%4);
00249                                                 } else {
00250                                                         // symbol can only have one charge of anything
00251                                                         // other than ignite/extinguish
00252                                                         quality += 1;
00253                                                 }
00254                                         } else {
00255                                                 frame = 19;
00256                                                 quality = 0;
00257                                         }
00258 
00259                                         item = ItemFactory::createItem(shape, frame, quality,
00260                                                                                                    Item::FLG_DISPOSABLE,
00261                                                                                                    0, 0, 0, true);
00262                                         item->moveToContainer(this);
00263                                         item->randomGumpLocation();
00264                                 }
00265 
00266                                 if (std::rand() % 10 < 2)
00267                                 {
00268                                         // demon talisman
00269                                         if (std::rand() % 10 < 2) {
00270                                                 // charged
00271                                                 frame = 9;
00272                                                 quality = 1 + (std::rand() % 2) +  // charges
00273                                                         ((10 + (std::rand()%2))<<8);   // spell
00274                                         } else {
00275                                                 frame = 18;
00276                                                 quality = 0;
00277                                         }
00278 
00279                                         item = ItemFactory::createItem(shape, frame, quality,
00280                                                                                                    Item::FLG_DISPOSABLE,
00281                                                                                                    0, 0, 0, true);
00282                                         item->moveToContainer(this);
00283                                         item->randomGumpLocation();
00284                                 }
00285 
00286                         } else {
00287                                 pout << "Unhandled special treasure: " << ti.special
00288                                          << std::endl;
00289                         }
00290                         continue;
00291                 }
00292 
00293                 // if shapes.size() == 1 and the given shape is SF_QUANTITY,
00294                 // then produce a stack of that shape (ignoring frame)
00295 
00296                 if (ti.shapes.size() == 1) {
00297                         uint32 shape = ti.shapes[0];
00298                         ShapeInfo* si = mainshapes->getShapeInfo(shape);
00299                         if (!si) {
00300                                 perr << "Trying to create treasure with an invalid shape ("
00301                                          << shape << ")" << std::endl;
00302                                 continue;
00303                         }
00304                         if (si->hasQuantity()) {
00305                                 // CHECKME: which flags?
00306                                 item = ItemFactory::createItem(shape,
00307                                                                                            0, // frame
00308                                                                                            count, // quality
00309                                                                                            Item::FLG_DISPOSABLE, // flags
00310                                                                                            0, // npcnum,
00311                                                                                            0, // mapnum
00312                                                                                            0, true); // ext. flags, objid
00313                                 item->moveToContainer(this);
00314                                 item->randomGumpLocation();
00315                                 item->callUsecodeEvent_combine(); // this sets the right frame
00316                                 continue;
00317                         }
00318                 }
00319 
00320                 if (ti.shapes.empty() || ti.frames.empty()) {
00321                         perr << "No shape/frame set in treasure" << std::endl;
00322                         continue;
00323                 }
00324 
00325                 // we need to produce a number of items
00326                 for (int i = 0; i < count; ++i) {
00327                         // pick shape
00328                         int n = std::rand() % ti.shapes.size();
00329                         uint32 shape = ti.shapes[n];
00330 
00331                         // pick frame
00332                         n = std::rand() % ti.frames.size();
00333                         uint32 frame = ti.frames[n];
00334 
00335                         ShapeInfo* si = GameData::get_instance()->getMainShapes()->
00336                                 getShapeInfo(shape);
00337                         if (!si) {
00338                                 perr << "Trying to create treasure with an invalid shape ("
00339                                          << shape << ")" << std::endl;
00340                                 continue;
00341                         }
00342                         uint16 qual = 0;
00343                         if (si->hasQuantity())
00344                                 qual = 1;
00345 
00346                         // CHECKME: flags?
00347                         item = ItemFactory::createItem(shape,
00348                                                                                    frame, // frame
00349                                                                                    qual, // quality
00350                                                                                    Item::FLG_DISPOSABLE, // flags
00351                                                                                    0, // npcnum,
00352                                                                                    0, // mapnum
00353                                                                                    0, true); // ext. flags, objid
00354                         item->moveToContainer(this);
00355                         item->randomGumpLocation();
00356                 }
00357         }
00358 
00359         return true;
00360 }
00361 
00362 bool Actor::removeItem(Item* item)
00363 {
00364         if (!Container::removeItem(item)) return false;
00365 
00366         item->clearFlag(FLG_EQUIPPED); // unequip if necessary
00367 
00368         return true;
00369 }
00370 
00371 bool Actor::setEquip(Item* item, bool checkwghtvol)
00372 {
00373         const unsigned int backpack_shape = 529; 
00374         uint32 equiptype = item->getShapeInfo()->equiptype;
00375         bool backpack = (item->getShape() == backpack_shape);
00376 
00377         // valid item type?
00378         if (equiptype == ShapeInfo::SE_NONE && !backpack) return false;
00379 
00380         // now check 'equipment slots'
00381         // we can have one item of each equipment type, plus one backpack
00382         std::list<Item*>::iterator iter;
00383         for (iter = contents.begin(); iter != contents.end(); ++iter)
00384         {
00385                 if ((*iter)->getObjId() == item->getObjId()) continue;
00386 
00387                 uint32 cet = (*iter)->getShapeInfo()->equiptype;
00388                 bool cbackpack = ((*iter)->getShape() == backpack_shape);
00389 
00390                 // already have an item with the same equiptype
00391                 if (cet == equiptype || (cbackpack && backpack)) return false;
00392         }
00393 
00394         if (!item->moveToContainer(this, checkwghtvol)) return false;
00395         item->clearFlag(FLG_CONTAINED);
00396         item->setFlag(FLG_EQUIPPED);
00397         item->setZ(equiptype);
00398 
00399         return true;
00400 }
00401 
00402 uint16 Actor::getEquip(uint32 type)
00403 {
00404         const unsigned int backpack_shape = 529; 
00405 
00406         std::list<Item*>::iterator iter;
00407         for (iter = contents.begin(); iter != contents.end(); ++iter)
00408         {
00409                 uint32 cet = (*iter)->getShapeInfo()->equiptype;
00410                 bool cbackpack = ((*iter)->getShape() == backpack_shape);
00411 
00412                 if (((*iter)->getFlags() & FLG_EQUIPPED) &&
00413                         (cet == type || (cbackpack && type == 7))) // !! constant
00414                 {
00415                         return (*iter)->getObjId();
00416                 }
00417         }
00418 
00419         return 0;
00420 }
00421 
00422 void Actor::teleport(int newmap, sint32 newx, sint32 newy, sint32 newz)
00423 {
00424         uint16 newmapnum = static_cast<uint16>(newmap);
00425 
00426         // Set the mapnum
00427         setMapNum(newmapnum);
00428 
00429         // Put it in the void
00430         moveToEtherealVoid();
00431 
00432         // Move it to this map
00433         if (newmapnum == World::get_instance()->getCurrentMap()->getNum())
00434         {
00435 #ifdef DEBUG
00436                 perr << "Actor::teleport: " << getObjId() << " to " << newmap << ","
00437                          << newx << "," << newy << "," << newz << std::endl;
00438 #endif
00439                 move(newx, newy, newz);
00440         }
00441         // Move it to another map
00442         else
00443         {
00444                 World::get_instance()->etherealRemove(objid);
00445                 x = newx;
00446                 y = newy;
00447                 z = newz;
00448         }
00449 } 
00450 
00451 uint16 Actor::doAnim(Animation::Sequence anim, int dir, unsigned int steps)
00452 {
00453         if (dir < 0 || dir > 8) {
00454                 perr << "Actor::doAnim: Invalid direction (" << dir << ")" <<std::endl;
00455                 return 0;
00456         }
00457 
00458 #if 0
00459         if (tryAnim(anim, dir)) {
00460                 perr << "Actor::doAnim: tryAnim = Ok!" << std::endl;
00461         } else {
00462                 perr << "Actor::doAnim: tryAnim = bad!" << std::endl;
00463         }
00464 #endif
00465 
00466         Process *p = new ActorAnimProcess(this, anim, dir, steps);
00467 
00468         return Kernel::get_instance()->addProcess(p);
00469 }
00470 
00471 bool Actor::hasAnim(Animation::Sequence anim)
00472 {
00473         AnimationTracker tracker;
00474 
00475         return tracker.init(this, anim, 0);
00476 }
00477 
00478 Animation::Result Actor::tryAnim(Animation::Sequence anim, int dir,
00479                                                                  unsigned int steps, PathfindingState* state)
00480 {
00481         if (dir < 0 || dir > 8) return Animation::FAILURE;
00482 
00483         if (dir == 8) dir = getDir();
00484 
00485         AnimationTracker tracker;
00486         if (!tracker.init(this, anim, dir, state))
00487                 return Animation::FAILURE;
00488 
00489         AnimAction * animaction = tracker.getAnimAction();
00490 
00491         if (!animaction) return Animation::FAILURE;
00492 
00493         unsigned int curstep = 0;
00494 
00495         while (tracker.step() && (!steps || curstep >= steps))
00496         {
00497                 curstep++;
00498         }
00499 
00500         if (tracker.isBlocked() &&
00501                 !(animaction->flags & AnimAction::AAF_UNSTOPPABLE))
00502         {
00503                 return Animation::FAILURE;
00504         }
00505 
00506         if (state) {
00507                 tracker.updateState(*state);
00508                 state->lastanim = anim;
00509                 state->direction = dir;
00510         }
00511 
00512 
00513         if (tracker.isUnsupported())
00514         {
00515                 return Animation::END_OFF_LAND;
00516         }
00517 
00518         // isUnsupported only checks for AFF_ONGROUND, we need either
00519         sint32 end[3], dims[3];
00520         getFootpadWorld(dims[0], dims[1], dims[2]);
00521         tracker.getPosition(end[0], end[1], end[2]);
00522 
00523         CurrentMap * cm = World::get_instance()->getCurrentMap();
00524 
00525         UCList uclist(2);
00526         LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
00527         cm->surfaceSearch(&uclist, script, sizeof(script),
00528                                           getObjId(), end, dims,
00529                                           false, true, false);
00530         for (uint32 i = 0; i < uclist.getSize(); i++)
00531         {
00532                 Item *item = getItem(uclist.getuint16(i));
00533                 if (item->getShapeInfo()->is_land())
00534                         return Animation::SUCCESS;
00535         }
00536 
00537         return Animation::END_OFF_LAND;
00538 }
00539 
00540 uint16 Actor::cSetActivity(int activity)
00541 {
00542         switch (activity) {
00543         case 0: // loiter
00544                 Kernel::get_instance()->addProcess(new LoiterProcess(this));
00545                 return Kernel::get_instance()->addProcess(new DelayProcess(1));
00546                 break;
00547         case 1: // combat
00548                 setInCombat();
00549                 return 0;
00550         case 2: // stand
00551                 // NOTE: temporary fall-throughs!
00552                 return doAnim(Animation::stand, 8);
00553 
00554         default:
00555                 perr << "Actor::cSetActivity: invalid activity (" << activity << ")"
00556                          << std::endl;
00557         }
00558 
00559         return 0;
00560 }
00561 
00562 uint32 Actor::getArmourClass()
00563 {
00564         ShapeInfo* si = getShapeInfo();
00565         if (si->monsterinfo)
00566                 return si->monsterinfo->armour_class;
00567         else
00568                 return 0;
00569 }
00570 
00571 uint16 Actor::getDefenseType()
00572 {
00573         ShapeInfo* si = getShapeInfo();
00574         if (si->monsterinfo)
00575                 return si->monsterinfo->defense_type;
00576         else
00577                 return 0;
00578 }
00579 
00580 sint16 Actor::getDefendingDex()
00581 {
00582         return getDex();
00583 }
00584 
00585 sint16 Actor::getAttackingDex()
00586 {
00587         return getDex();
00588 }
00589 
00590 uint16 Actor::getDamageType()
00591 {
00592         ShapeInfo* si = getShapeInfo();
00593         if (si->monsterinfo)
00594                 return si->monsterinfo->damage_type;
00595         else 
00596                 return WeaponInfo::DMG_NORMAL;
00597 }
00598 
00599 
00600 int Actor::getDamageAmount()
00601 {
00602         ShapeInfo* si = getShapeInfo();
00603         if (si->monsterinfo) {
00604 
00605                 int min = static_cast<int>(si->monsterinfo->min_dmg);
00606                 int max = static_cast<int>(si->monsterinfo->max_dmg);
00607                 
00608                 int damage = (std::rand() % (max - min + 1)) + min;
00609                 
00610                 return damage;
00611         } else {
00612                 return 1;
00613         }
00614 }
00615 
00616 
00617 void Actor::receiveHit(uint16 other, int dir, int damage, uint16 damage_type)
00618 {
00619         if (isDead())
00620                 return; // already dead, so don't bother
00621 
00622         Item* hitter = getItem(other);
00623         Actor* attacker = getActor(other);
00624 
00625         if (damage == 0 && attacker) {
00626                 damage = attacker->getDamageAmount();
00627         }
00628 
00629         if (damage_type == 0 && hitter) {
00630                 damage_type = hitter->getDamageType();
00631         }
00632 
00633         if (other == 1 && attacker->getLastAnim() != Animation::kick) {
00634                 // strength for kicks is accumulated in AvatarMoverProcess
00635                 MainActor* av = getMainActor();
00636                 av->accumulateStr(damage/4);
00637         }
00638 
00639         pout << "Actor " << getObjId() << " received hit from " << other
00640                  << " (dmg=" << damage << ",type=" << std::hex << damage_type
00641                  << std::dec << "). ";
00642 
00643         damage = calculateAttackDamage(other, damage, damage_type);
00644 
00645         if (!damage) {
00646                 pout << "No damage." << std::endl;
00647         } else {
00648                 pout << "Damage: " << damage << std::endl;
00649         }
00650 
00651         if (damage >= 4 && objid == 1 && attacker) {
00652                 // play blood sprite
00653                 int start = 0, end = 12;
00654                 if (dir > 2) {
00655                         start = 13; end = 25;
00656                 }
00657 
00658                 sint32 x,y,z;
00659                 getLocation(x,y,z);
00660                 z += (std::rand() % 24);
00661                 Process *sp = new SpriteProcess(620, start, end, 1, 1, x, y, z);
00662                 Kernel::get_instance()->addProcess(sp);
00663         }
00664 
00665         if (damage > 0 && !(getActorFlags() & (ACT_IMMORTAL | ACT_INVINCIBLE))) {
00666                 if (damage >= hitpoints) {
00667                         // we're dead
00668 
00669                         if (getActorFlags() & ACT_WITHSTANDDEATH) {
00670                                 // or maybe not...
00671 
00672                                 setHP(getMaxHP());
00673                                 AudioProcess* audioproc = AudioProcess::get_instance();
00674                                 if (audioproc) audioproc->playSFX(59, 0x60, objid, 0);
00675                                 clearActorFlag(ACT_WITHSTANDDEATH);
00676                         } else {
00677                                 die(damage_type);
00678                         }
00679                         return;
00680                 }
00681 
00682                 // not dead yet
00683                 setHP(static_cast<uint16>(hitpoints - damage));
00684         }
00685 
00686         ProcId fallingprocid = 0;
00687         if (objid == 1 && damage > 0) {
00688                 if ((damage_type & WeaponInfo::DMG_FALLING) && damage >= 6) {
00689                         // high falling damage knocks you down
00690                         doAnim(Animation::fallBackwards, 8);
00691 
00692                         // TODO: shake head after getting back up when not in combat
00693                         return;
00694                 }
00695 
00696                 // got hit, so abort current animation
00697                 fallingprocid = killAllButFallAnims(false);
00698         }
00699 
00700         // if avatar was blocking; do a quick stopBlock/startBlock and play SFX
00701         if (objid == 1 && getLastAnim() == Animation::startBlock) {
00702                 ProcId anim1pid = doAnim(Animation::stopBlock, 8);
00703                 ProcId anim2pid = doAnim(Animation::startBlock, 8);
00704 
00705                 Process* anim1proc = Kernel::get_instance()->getProcess(anim1pid);
00706                 Process* anim2proc = Kernel::get_instance()->getProcess(anim2pid);
00707                 assert(anim1proc);
00708                 assert(anim2proc);
00709                 anim2proc->waitFor(anim1proc);
00710 
00711                 int sfx;
00712                 if (damage)
00713                         sfx = 50 + (std::rand() % 2); // constants!
00714                 else
00715                         sfx = 20 + (std::rand() % 3); // constants!
00716                 AudioProcess* audioproc = AudioProcess::get_instance();
00717                 if (audioproc) audioproc->playSFX(sfx, 0x60, objid, 0);
00718                 return;
00719         }
00720 
00721         // TODO: target needs to stumble/fall/call for help/...(?)
00722 
00723         if (objid != 1) {
00724                 ObjId target = 1;
00725                 if (attacker)
00726                         target = attacker->getObjId();
00727                 if (!isInCombat())
00728                         setInCombat();
00729 
00730                 CombatProcess* cp = getCombatProcess();
00731                 assert(cp);
00732                 cp->setTarget(target);
00733 
00734                 if (target == 1) {
00735                         // call for help
00736                 }
00737         }
00738 
00739         if (damage && !fallingprocid) {
00740                 ProcId anim1pid = doAnim(Animation::stumbleBackwards, dir);
00741                 ProcId anim2pid;
00742                 if (isInCombat())
00743                         // not doing this would cause you to re-draw your weapon when hit
00744                         anim2pid = doAnim(Animation::combatStand, dir);
00745                 else
00746                         anim2pid = doAnim(Animation::stand, dir);
00747                 Process* anim1proc = Kernel::get_instance()->getProcess(anim1pid);
00748                 Process* anim2proc = Kernel::get_instance()->getProcess(anim2pid);
00749                 assert(anim1proc);
00750                 assert(anim2proc);
00751                 anim2proc->waitFor(anim1proc);
00752         }
00753 }
00754 
00755 ProcId Actor::die(uint16 damageType)
00756 {
00757         setHP(0);
00758         setActorFlag(ACT_DEAD);
00759         clearActorFlag(ACT_INCOMBAT);
00760 
00761         ProcId animprocid = 0;
00762 #if 1
00763         animprocid = killAllButFallAnims(true);
00764 #else
00765         Kernel::get_instance()->killProcesses(getObjId(), 6, true); // CONSTANT!
00766 #endif
00767 
00768         if (!animprocid)
00769                 animprocid = doAnim(Animation::die, getDir());
00770 
00771 
00772         MainActor* avatar = getMainActor();
00773         // if hostile to avatar
00774         if (getEnemyAlignment() & avatar->getAlignment()) {
00775                 if (avatar->isInCombat()) {
00776                         // play victory fanfare
00777                         MusicProcess::get_instance()->playCombatMusic(109);
00778                         // and resume combat music afterwards
00779                         MusicProcess::get_instance()->queueMusic(98);
00780                 }
00781         }
00782 
00783 
00784         destroyContents();
00785         giveTreasure();
00786 
00787         ShapeInfo* shapeinfo = getShapeInfo();
00788         MonsterInfo* mi = 0;
00789         if (shapeinfo) mi = shapeinfo->monsterinfo;
00790 
00791         if (mi && mi->resurrection && !(damageType & WeaponInfo::DMG_FIRE)) {
00792                 // this monster will be resurrected after a while
00793 
00794                 pout << "Actor::die: scheduling resurrection" << std::endl;
00795 
00796                 int timeout = ((std::rand() % 25) + 5) * 30; // 5-30 seconds
00797 
00798                 Process* resproc = new ResurrectionProcess(this);
00799                 Kernel::get_instance()->addProcess(resproc);
00800 
00801                 Process* delayproc = new DelayProcess(timeout);
00802                 Kernel::get_instance()->addProcess(delayproc);
00803 
00804                 ProcId animpid = doAnim(Animation::standUp, 8);
00805                 Process* animproc = Kernel::get_instance()->getProcess(animpid);
00806                 assert(animproc);
00807 
00808                 resproc->waitFor(delayproc);
00809                 animproc->waitFor(resproc);
00810         }
00811 
00812         if (mi && mi->explode) {
00813                 // this monster explodes when it dies
00814 
00815                 pout << "Actor::die: exploding" << std::endl;
00816 
00817                 int count = 5;
00818                 Shape* explosionshape = GameData::get_instance()->getMainShapes()
00819                         ->getShape(mi->explode);
00820                 assert(explosionshape);
00821                 unsigned int framecount = explosionshape->frameCount();
00822 
00823                 for (int i = 0; i < count; ++i) {
00824                         Item* piece = ItemFactory::createItem(mi->explode,
00825                                                                                                   std::rand()%framecount,
00826                                                                                                   0, // qual
00827                                                                                                   Item::FLG_FAST_ONLY, //flags,
00828                                                                                                   0, // npcnum
00829                                                                                                   0, // mapnum
00830                                                                                                   0, true // ext. flags, objid
00831                                 );
00832                         piece->move(x - 128 + 32*(std::rand()%6),
00833                                                 y - 128 + 32*(std::rand()%6),
00834                                                 z + std::rand()%8 ); // move to near actor's position
00835                         piece->hurl(-25 + (std::rand()%50),
00836                                                 -25 + (std::rand()%50),
00837                                                 10 + (std::rand()%10),
00838                                                 4); // (wrong?) CONSTANTS!
00839                 }
00840         }
00841 
00842         return animprocid;
00843 }
00844 
00845 void Actor::killAllButCombatProcesses()
00846 {
00847         // loop over all processes, keeping only the relevant ones
00848         ProcessIter iter = Kernel::get_instance()->getProcessBeginIterator();
00849         ProcessIter endproc = Kernel::get_instance()->getProcessEndIterator();
00850         for (; iter != endproc; ++iter) {
00851                 Process* p = *iter;
00852                 if (!p) continue;
00853                 if (p->getItemNum() != objid) continue;
00854                 if (p->is_terminated()) continue;
00855 
00856                 uint16 type = p->getType();
00857 
00858                 if (type != 0xF0 && type != 0xF2 && type != 0x208 && type != 0x21D &&
00859                         type != 0x220 && type != 0x238 && type != 0x243)
00860                 {
00861                         p->fail();
00862                 }
00863         }
00864 }
00865 
00866 ProcId Actor::killAllButFallAnims(bool death)
00867 {
00868         ProcId fallproc = 0;
00869 
00870         Kernel* kernel = Kernel::get_instance();
00871 
00872         if (death) {
00873                 // if dead, we want to kill everything but animations
00874                 kernel->killProcessesNotOfType(objid, 0xF0, true);
00875         } else {
00876                 // otherwise, need to focus on combat, so kill everything else
00877                 killAllButCombatProcesses();
00878         }
00879 
00880         // loop over all animation processes, keeping only the relevant ones
00881         ProcessIter iter = Kernel::get_instance()->getProcessBeginIterator();
00882         ProcessIter endproc = Kernel::get_instance()->getProcessEndIterator();
00883         for (; iter != endproc; ++iter) {
00884                 ActorAnimProcess* p = p_dynamic_cast<ActorAnimProcess*>(*iter);
00885                 if (!p) continue;
00886                 if (p->getItemNum() != objid) continue;
00887                 if (p->is_terminated()) continue;
00888 
00889                 Animation::Sequence action = p->getAction();
00890 
00891                 if (action == Animation::die) {
00892                         fallproc = p->getPid();
00893                         continue;
00894                 }
00895 
00896                 if (!death && action == Animation::standUp) {
00897                         fallproc = p->getPid();
00898                 } else {
00899                         p->fail();
00900                 }
00901         }
00902 
00903         return fallproc;
00904 }
00905 
00906 int Actor::calculateAttackDamage(uint16 other, int damage, uint16 damage_type)
00907 {
00908         Actor* attacker = getActor(other);
00909 
00910         uint16 defense_type = getDefenseType();
00911 
00912         // most damage types are blocked straight away by defense types
00913         damage_type &= ~(defense_type & ~(WeaponInfo::DMG_MAGIC  |
00914                                                                           WeaponInfo::DMG_UNDEAD |
00915                                                                           WeaponInfo::DMG_PIERCE));
00916 
00917         // immunity to non-magical weapons
00918         if ((defense_type & WeaponInfo::DMG_MAGIC) &&
00919                 !(damage_type & WeaponInfo::DMG_MAGIC))
00920         {
00921                 damage = 0;
00922         }
00923 
00924         bool slayer = false;
00925 
00926         // special attacks
00927         if (damage && damage_type)
00928         {
00929                 if (damage_type & WeaponInfo::DMG_SLAYER) {
00930                         if (std::rand() % 10 == 0) {
00931                                 slayer = true;
00932                                 damage = 255; // instant kill
00933                         }
00934                 }
00935 
00936                 if ((damage_type & WeaponInfo::DMG_UNDEAD) &&
00937                         (defense_type & WeaponInfo::DMG_UNDEAD))
00938                 {
00939                         damage *= 2; // double damage against undead
00940                 }
00941 
00942                 if ((defense_type & WeaponInfo::DMG_PIERCE) &&
00943                         !(damage_type & (WeaponInfo::DMG_BLADE |
00944                                                          WeaponInfo::DMG_FIRE  |
00945                                                          WeaponInfo::DMG_PIERCE)))
00946                 {
00947                         damage /= 2; // resistance to blunt damage
00948                 }
00949         } else {
00950                 damage = 0;
00951         }
00952 
00953         // armour
00954         if (damage && !(damage_type & WeaponInfo::DMG_PIERCE) && !slayer)
00955         {
00956                 // blocking?
00957                 if ((getLastAnim() == Animation::startBlock ||
00958                          getLastAnim() == Animation::stopBlock) &&
00959                         !(getActorFlags() & ACT_STUNNED))
00960                 {
00961                         damage -= getStr() / 5;
00962                 }
00963 
00964                 int ACmod = 3 * getArmourClass();
00965                 if (damage_type & WeaponInfo::DMG_FIRE)
00966                         ACmod /= 2; // armour doesn't protect from fire as well
00967 
00968                 if (getActorFlags() & ACT_STUNNED)
00969                         ACmod /= 2; // stunned?
00970 
00971                 if (ACmod > 100) ACmod = 100;
00972 
00973                 // TODO: replace rounding bias by something random
00974                 damage = ((100 - ACmod) * damage) / 100;
00975 
00976                 if (damage < 0) damage = 0;
00977         }
00978 
00979         // to-hit
00980         if (damage && !(damage_type & WeaponInfo::DMG_PIERCE) && attacker)
00981         {
00982                 bool hit = false;
00983                 sint16 attackdex = attacker->getAttackingDex();
00984                 sint16 defenddex = getDefendingDex();
00985                 if (attackdex < 0) attackdex = 0;
00986                 if (defenddex <= 0) defenddex = 1;
00987 
00988                 if ((getActorFlags() & ACT_STUNNED) ||
00989                         (rand() % (attackdex + 3) > rand() % defenddex))
00990                 {
00991                         hit = true;
00992                 }
00993 
00994                 // TODO: give avatar an extra chance to hit monsters
00995                 //       with defense_type DMG_PIERCE
00996 
00997                 if (hit && other == 1) {
00998                         MainActor* av = getMainActor();
00999                         if (attackdex > defenddex)
01000                                 av->accumulateDex(2*(attackdex-defenddex));
01001                         else
01002                                 av->accumulateDex(2);
01003                 }
01004 
01005                 if (!hit) {
01006                         damage = 0;
01007                 }
01008         }
01009 
01010         return damage;
01011 }
01012 
01013 CombatProcess* Actor::getCombatProcess()
01014 {
01015         Process* p = Kernel::get_instance()->findProcess(objid, 0xF2); // CONSTANT!
01016         if (!p) return 0;
01017         CombatProcess* cp = p_dynamic_cast<CombatProcess*>(p);
01018         assert(cp);
01019 
01020         return cp;
01021 }
01022 
01023 void Actor::setInCombat()
01024 {
01025         if ((actorflags & ACT_INCOMBAT) != 0) return;
01026 
01027         assert(getCombatProcess() == 0);
01028 
01029         // kill any processes belonging to this actor
01030         Kernel::get_instance()->killProcesses(getObjId(), 6, true);
01031 
01032         // perform special actions
01033         ProcId castproc = callUsecodeEvent_cast(0);
01034 
01035         CombatProcess* cp = new CombatProcess(this);
01036         Kernel::get_instance()->addProcess(cp);
01037  
01038         // wait for any special actions to finish before starting to fight
01039         if (castproc)
01040                 cp->waitFor(castproc);
01041 
01042         setActorFlag(ACT_INCOMBAT);
01043 }
01044 
01045 void Actor::clearInCombat()
01046 {
01047         if ((actorflags & ACT_INCOMBAT) == 0) return;
01048 
01049         CombatProcess* cp = getCombatProcess();
01050         cp->terminate();
01051 
01052         clearActorFlag(ACT_INCOMBAT);
01053 }
01054 
01055 bool Actor::areEnemiesNear()
01056 {
01057         UCList uclist(2);
01058         LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
01059         CurrentMap* currentmap = World::get_instance()->getCurrentMap();
01060         currentmap->areaSearch(&uclist, script,sizeof(script), this, 0x800, false);
01061 
01062         for (unsigned int i = 0; i < uclist.getSize(); ++i) {
01063                 Actor *npc = getActor(uclist.getuint16(i));
01064                 if (!npc) continue;
01065                 if (npc == this) continue;
01066 
01067                 if (npc->getActorFlags() & (ACT_DEAD | ACT_FEIGNDEATH)) continue;
01068                 if (!(npc->getActorFlags() & ACT_INCOMBAT)) continue;
01069 
01070                 // TODO: check if hostile.
01071                 // Might not be strictly necessary, though. This function is only
01072                 // used on the avatar, and any NPCs in combat mode around the avatar
01073                 // are most likely hostile... (and if they're not hostile, they're
01074                 // probably in combat mode because something hostile _is_ nearby)
01075 
01076                 return true;
01077         }
01078 
01079         return false;
01080 }
01081 
01082 uint16 Actor::schedule(uint32 time)
01083 {
01084         if (isDead())
01085                 return 0;
01086 
01087         uint32 ret = callUsecodeEvent_schedule(time);
01088 
01089         return static_cast<uint16>(ret);
01090 }
01091 
01092 //static
01093 Actor* Actor::createActor(uint32 shape, uint32 frame)
01094 {
01095         Actor* newactor = ItemFactory::createActor(shape, frame, 0,
01096                                                                                            Item::FLG_IN_NPC_LIST,
01097                                                                                            0, 0, 0, true);
01098         if (!newactor)
01099                 return 0;
01100         uint16 objID = newactor->getObjId();
01101 
01102         // set stats
01103         if (!newactor->loadMonsterStats()) {
01104                 perr << "I_createActor failed to set stats for actor (" << shape
01105                          << ")." << std::endl;
01106         }
01107 
01108         Actor* av = getMainActor();
01109         newactor->setMapNum(av->getMapNum());
01110         newactor->setNpcNum(objID);
01111         newactor->setFlag(FLG_ETHEREAL);
01112         World::get_instance()->etherealPush(objID);
01113 
01114         return newactor;
01115 }
01116 
01117 
01118 void Actor::dumpInfo()
01119 {
01120         Container::dumpInfo();
01121 
01122         pout << "hp: " << hitpoints << ", mp: " << mana << ", str: " << strength
01123                  << ", dex: " << dexterity << ", int: " << intelligence
01124                  << ", ac: " << getArmourClass() << ", defense: " << std::hex
01125                  << getDefenseType() << " align: " << getAlignment() << " enemy: "
01126                  << getEnemyAlignment() << ", flags: " << actorflags
01127                  << std::dec << std::endl;
01128 }
01129 
01130 void Actor::saveData(ODataSource* ods)
01131 {
01132         Container::saveData(ods);
01133         ods->write2(strength);
01134         ods->write2(dexterity);
01135         ods->write2(intelligence);
01136         ods->write2(hitpoints);
01137         ods->write2(mana);
01138         ods->write2(alignment);
01139         ods->write2(enemyalignment);
01140         ods->write2(lastanim);
01141         ods->write2(animframe);
01142         ods->write2(direction);
01143         ods->write4(fallstart);
01144         ods->write4(actorflags);
01145         ods->write1(unk0C);
01146 }
01147 
01148 bool Actor::loadData(IDataSource* ids, uint32 version)
01149 {
01150         if (!Container::loadData(ids, version)) return false;
01151 
01152         strength = static_cast<sint16>(ids->read2());
01153         dexterity = static_cast<sint16>(ids->read2());
01154         intelligence = static_cast<sint16>(ids->read2());
01155         hitpoints = ids->read2();
01156         mana = static_cast<sint16>(ids->read2());
01157         alignment = ids->read2();
01158         enemyalignment = ids->read2();
01159         lastanim = static_cast<Animation::Sequence>(ids->read2());
01160         animframe = ids->read2();
01161         direction = ids->read2();
01162         fallstart = ids->read4();
01163         actorflags = ids->read4();
01164         unk0C = ids->read1();
01165 
01166         return true;
01167 }
01168 
01169 
01170 uint32 Actor::I_isNPC(const uint8* args, unsigned int /*argsize*/)
01171 {
01172         ARG_ACTOR_FROM_PTR(actor);
01173         if (!actor) return 0;
01174         return 1;
01175 }
01176 
01177 uint32 Actor::I_getMap(const uint8* args, unsigned int /*argsize*/)
01178 {
01179         ARG_ACTOR_FROM_PTR(actor);
01180         if (!actor) return 0;
01181 
01182         return actor->getMapNum();
01183 }
01184 
01185 uint32 Actor::I_teleport(const uint8* args, unsigned int /*argsize*/)
01186 {
01187         ARG_ACTOR_FROM_PTR(actor);
01188         ARG_UINT16(newx);
01189         ARG_UINT16(newy);
01190         ARG_UINT16(newz);
01191         ARG_UINT16(newmap);
01192         if (!actor) return 0;
01193 
01194         actor->teleport(newmap,newx,newy,newz);
01195         return 0;
01196 }
01197 
01198 uint32 Actor::I_doAnim(const uint8* args, unsigned int /*argsize*/)
01199 {
01200         ARG_ACTOR_FROM_PTR(actor);
01201         ARG_UINT16(anim);
01202         ARG_UINT16(dir); // seems to be 0-8
01203         ARG_UINT16(unk1); // this is almost always 10000 in U8.Maybe speed-related?
01204         ARG_UINT16(unk2); // appears to be 0 or 1. Some flag?
01205 
01206         if (!actor) return 0;
01207 
01208         return actor->doAnim(static_cast<Animation::Sequence>(anim), dir);
01209 }
01210 
01211 uint32 Actor::I_getDir(const uint8* args, unsigned int /*argsize*/)
01212 {
01213         ARG_ACTOR_FROM_PTR(actor);
01214         if (!actor) return 0;
01215 
01216         return actor->getDir();
01217 }
01218 
01219 uint32 Actor::I_getLastAnimSet(const uint8* args, unsigned int /*argsize*/)
01220 {
01221         ARG_ACTOR_FROM_PTR(actor);
01222         if (!actor) return 0;
01223 
01224         return actor->getLastAnim();
01225 }
01226 
01227 uint32 Actor::I_getStr(const uint8* args, unsigned int /*argsize*/)
01228 {
01229         ARG_ACTOR_FROM_PTR(actor);
01230         if (!actor) return 0;
01231 
01232         return actor->getStr();
01233 }
01234 
01235 uint32 Actor::I_getDex(const uint8* args, unsigned int /*argsize*/)
01236 {
01237         ARG_ACTOR_FROM_PTR(actor);
01238         if (!actor) return 0;
01239 
01240         return actor->getDex();
01241 }
01242 
01243 uint32 Actor::I_getInt(const uint8* args, unsigned int /*argsize*/)
01244 {
01245         ARG_ACTOR_FROM_PTR(actor);
01246         if (!actor) return 0;
01247 
01248         return actor->getInt();
01249 }
01250 
01251 uint32 Actor::I_getHp(const uint8* args, unsigned int /*argsize*/)
01252 {
01253         ARG_ACTOR_FROM_PTR(actor);
01254         if (!actor) return 0;
01255 
01256         return actor->getHP();
01257 }
01258 
01259 uint32 Actor::I_getMana(const uint8* args, unsigned int /*argsize*/)
01260 {
01261         ARG_ACTOR_FROM_PTR(actor);
01262         if (!actor) return 0;
01263 
01264         return actor->getMana();
01265 }
01266 
01267 uint32 Actor::I_getAlignment(const uint8* args, unsigned int /*argsize*/)
01268 {
01269         ARG_ACTOR_FROM_PTR(actor);
01270         if (!actor) return 0;
01271 
01272         return actor->getAlignment();
01273 }
01274 
01275 uint32 Actor::I_getEnemyAlignment(const uint8* args, unsigned int /*argsize*/)
01276 {
01277         ARG_ACTOR_FROM_PTR(actor);
01278         if (!actor) return 0;
01279 
01280         return actor->getEnemyAlignment();
01281 }
01282 
01283 uint32 Actor::I_setStr(const uint8* args, unsigned int /*argsize*/)
01284 {
01285         ARG_ACTOR_FROM_PTR(actor);
01286         ARG_SINT16(str);
01287         if (!actor) return 0;
01288 
01289         actor->setStr(str);
01290         return 0;
01291 }
01292 
01293 uint32 Actor::I_setDex(const uint8* args, unsigned int /*argsize*/)
01294 {
01295         ARG_ACTOR_FROM_PTR(actor);
01296         ARG_SINT16(dex);
01297         if (!actor) return 0;
01298 
01299         actor->setDex(dex);
01300         return 0;
01301 }
01302 
01303 uint32 Actor::I_setInt(const uint8* args, unsigned int /*argsize*/)
01304 {
01305         ARG_ACTOR_FROM_PTR(actor);
01306         ARG_SINT16(int_);
01307         if (!actor) return 0;
01308 
01309         actor->setStr(int_);
01310         return 0;
01311 }
01312 
01313 uint32 Actor::I_setHp(const uint8* args, unsigned int /*argsize*/)
01314 {
01315         ARG_ACTOR_FROM_PTR(actor);
01316         ARG_UINT16(hp);
01317         if (!actor) return 0;
01318 
01319         actor->setHP(hp);
01320         return 0;
01321 }
01322 
01323 uint32 Actor::I_setMana(const uint8* args, unsigned int /*argsize*/)
01324 {
01325         ARG_ACTOR_FROM_PTR(actor);
01326         ARG_SINT16(mp);
01327         if (!actor) return 0;
01328 
01329         actor->setMana(mp);
01330         return 0;
01331 }
01332 
01333 uint32 Actor::I_setAlignment(const uint8* args, unsigned int /*argsize*/)
01334 {
01335         ARG_ACTOR_FROM_PTR(actor);
01336         ARG_UINT16(a);
01337         if (!actor) return 0;
01338 
01339         actor->setAlignment(a);
01340         return 0;
01341 }
01342 
01343 uint32 Actor::I_setEnemyAlignment(const uint8* args, unsigned int /*argsize*/)
01344 {
01345         ARG_ACTOR_FROM_PTR(actor);
01346         ARG_UINT16(a);
01347         if (!actor) return 0;
01348 
01349         actor->setEnemyAlignment(a);
01350         return 0;
01351 }
01352 
01353 uint32 Actor::I_isInCombat(const uint8* args, unsigned int /*argsize*/)
01354 {
01355         ARG_ACTOR_FROM_PTR(actor);
01356         if (!actor) return 0;
01357 
01358         if (actor->isInCombat())
01359                 return 1;
01360         else
01361                 return 0;
01362 }
01363 
01364 uint32 Actor::I_setInCombat(const uint8* args, unsigned int /*argsize*/)
01365 {
01366         ARG_ACTOR_FROM_PTR(actor);
01367         if (!actor) return 0;
01368 
01369         actor->setInCombat();
01370 
01371         return 0;
01372 }
01373 
01374 uint32 Actor::I_clrInCombat(const uint8* args, unsigned int /*argsize*/)
01375 {
01376         ARG_ACTOR_FROM_PTR(actor);
01377         if (!actor) return 0;
01378 
01379         actor->clearInCombat();
01380 
01381         return 0;
01382 }
01383 
01384 uint32 Actor::I_setTarget(const uint8* args, unsigned int /*argsize*/)
01385 {
01386         ARG_ACTOR_FROM_PTR(actor);
01387         ARG_UINT16(target);
01388         if (!actor) return 0;
01389 
01390         CombatProcess* cp = actor->getCombatProcess();
01391         if (!cp) {
01392                 actor->setInCombat();
01393                 cp = actor->getCombatProcess();
01394         }
01395         if (!cp) {
01396                 perr << "Actor::I_setTarget: failed to enter combat mode"
01397                          << std::endl;
01398                 return 0;
01399         }
01400 
01401         cp->setTarget(target);
01402 
01403         return 0;
01404 }
01405 
01406 uint32 Actor::I_getTarget(const uint8* args, unsigned int /*argsize*/)
01407 {
01408         ARG_ACTOR_FROM_PTR(actor);
01409         if (!actor) return 0;
01410 
01411         CombatProcess* cp = actor->getCombatProcess();
01412 
01413         if (!cp) return 0;
01414 
01415         return static_cast<uint32>(cp->getTarget());
01416 }
01417 
01418 
01419 uint32 Actor::I_isEnemy(const uint8* args, unsigned int /*argsize*/)
01420 {
01421         ARG_ACTOR_FROM_PTR(actor);
01422         ARG_ACTOR_FROM_ID(other);
01423         if (!actor) return 0;
01424         if (!other) return 0;
01425 
01426         if (actor->getEnemyAlignment() & other->getAlignment())
01427                 return 1;
01428         else
01429                 return 0;
01430 }
01431 
01432 uint32 Actor::I_isDead(const uint8* args, unsigned int /*argsize*/)
01433 {
01434         ARG_ACTOR_FROM_PTR(actor);
01435         if (!actor) return 0;
01436 
01437         if (actor->isDead())
01438                 return 1;
01439         else
01440                 return 0;
01441 }
01442 
01443 uint32 Actor::I_setDead(const uint8* args, unsigned int /*argsize*/)
01444 {
01445         ARG_ACTOR_FROM_PTR(actor);
01446         if (!actor) return 0;
01447 
01448         actor->setActorFlag(ACT_DEAD);
01449 
01450         return 0;
01451 }
01452 
01453 uint32 Actor::I_clrDead(const uint8* args, unsigned int /*argsize*/)
01454 {
01455         ARG_ACTOR_FROM_PTR(actor);
01456         if (!actor) return 0;
01457 
01458         actor->clearActorFlag(ACT_DEAD);
01459 
01460         return 0;
01461 }
01462 
01463 uint32 Actor::I_isImmortal(const uint8* args, unsigned int /*argsize*/)
01464 {
01465         ARG_ACTOR_FROM_PTR(actor);
01466         if (!actor) return 0;
01467 
01468         if (actor->getActorFlags() & ACT_IMMORTAL)
01469                 return 1;
01470         else
01471                 return 0;
01472 }
01473 
01474 uint32 Actor::I_setImmortal(const uint8* args, unsigned int /*argsize*/)
01475 {
01476         ARG_ACTOR_FROM_PTR(actor);
01477         if (!actor) return 0;
01478 
01479         actor->setActorFlag(ACT_IMMORTAL);
01480         actor->clearActorFlag(ACT_INVINCIBLE);
01481 
01482         return 0;
01483 }
01484 
01485 uint32 Actor::I_clrImmortal(const uint8* args, unsigned int /*argsize*/)
01486 {
01487         ARG_ACTOR_FROM_PTR(actor);
01488         if (!actor) return 0;
01489 
01490         actor->clearActorFlag(ACT_IMMORTAL);
01491 
01492         return 0;
01493 }
01494 
01495 uint32 Actor::I_isWithstandDeath(const uint8* args, unsigned int /*argsize*/)
01496 {
01497         ARG_ACTOR_FROM_PTR(actor);
01498         if (!actor) return 0;
01499 
01500         if (actor->getActorFlags() & ACT_WITHSTANDDEATH)
01501                 return 1;
01502         else
01503                 return 0;
01504 }
01505 
01506 uint32 Actor::I_setWithstandDeath(const uint8* args, unsigned int /*argsize*/)
01507 {
01508         ARG_ACTOR_FROM_PTR(actor);
01509         if (!actor) return 0;
01510 
01511         actor->setActorFlag(ACT_WITHSTANDDEATH);
01512 
01513         return 0;
01514 }
01515 
01516 uint32 Actor::I_clrWithstandDeath(const uint8* args, unsigned int /*argsize*/)
01517 {
01518         ARG_ACTOR_FROM_PTR(actor);
01519         if (!actor) return 0;
01520 
01521         actor->clearActorFlag(ACT_WITHSTANDDEATH);
01522 
01523         return 0;
01524 }
01525 
01526 uint32 Actor::I_isFeignDeath(const uint8* args, unsigned int /*argsize*/)
01527 {
01528         ARG_ACTOR_FROM_PTR(actor);
01529         if (!actor) return 0;
01530 
01531         if (actor->getActorFlags() & ACT_FEIGNDEATH)
01532                 return 1;
01533         else
01534                 return 0;
01535 }
01536 
01537 uint32 Actor::I_setFeignDeath(const uint8* args, unsigned int /*argsize*/)
01538 {
01539         ARG_ACTOR_FROM_PTR(actor);
01540         if (!actor) return 0;
01541 
01542         if (actor->getActorFlags() & ACT_FEIGNDEATH)
01543                 return 0;
01544 
01545         actor->setActorFlag(ACT_FEIGNDEATH);
01546 
01547         ProcId animfallpid = actor->doAnim(Animation::die, 8);
01548         Process* animfallproc = Kernel::get_instance()->getProcess(animfallpid);
01549         assert(animfallproc);
01550 
01551         ProcId animstandpid = actor->doAnim(Animation::standUp, 8);
01552         Process* animstandproc = Kernel::get_instance()->getProcess(animstandpid);
01553         assert(animstandproc);
01554 
01555         Process* delayproc = new DelayProcess(900); // 30 seconds
01556         Kernel::get_instance()->addProcess(delayproc);
01557         
01558         Process* clearproc = new ClearFeignDeathProcess(actor);
01559         Kernel::get_instance()->addProcess(clearproc);
01560         
01561         // do them in order (fall, stand, wait, clear)
01562 
01563         clearproc->waitFor(delayproc);
01564         delayproc->waitFor(animstandproc);
01565         animstandproc->waitFor(animfallproc);
01566 
01567         return 0;
01568 }
01569 
01570 uint32 Actor::I_clrFeignDeath(const uint8* args, unsigned int /*argsize*/)
01571 {
01572         ARG_ACTOR_FROM_PTR(actor);
01573         if (!actor) return 0;
01574 
01575         actor->clearActorFlag(ACT_FEIGNDEATH);
01576 
01577         return 0;
01578 }
01579 
01580 uint32 Actor::I_pathfindToItem(const uint8* args, unsigned int /*argsize*/)
01581 {
01582         ARG_ACTOR_FROM_PTR(actor);
01583         ARG_OBJID(id2);
01584         Item* item = getItem(id2);
01585         if (!actor) return 0;
01586         if (!item) return 0;
01587 
01588         return Kernel::get_instance()->addProcess(
01589                 new PathfinderProcess(actor,id2));
01590 }
01591 
01592 uint32 Actor::I_pathfindToPoint(const uint8* args, unsigned int /*argsize*/)
01593 {
01594         ARG_ACTOR_FROM_PTR(actor);
01595         ARG_UINT16(x);
01596         ARG_UINT16(y);
01597         ARG_UINT16(z);
01598         ARG_NULL16(); // unknown. Only one instance of this in U8, value is 5.
01599         if (!actor) return 0;
01600 
01601         return Kernel::get_instance()->addProcess(
01602                 new PathfinderProcess(actor,x,y,z));
01603 }
01604 
01605 uint32 Actor::I_areEnemiesNear(const uint8* args, unsigned int /*argsize*/)
01606 {
01607         ARG_ACTOR_FROM_PTR(actor);
01608         if (!actor) return 0;
01609 
01610         if (actor->areEnemiesNear())
01611                 return 1;
01612         else
01613                 return 0;
01614 }
01615 
01616 uint32 Actor::I_isBusy(const uint8* args, unsigned int /*argsize*/)
01617 {
01618         ARG_UC_PTR(ptr);
01619         uint16 id = UCMachine::ptrToObject(ptr);
01620 
01621         uint32 count = Kernel::get_instance()->getNumProcesses(id, 0x00F0);
01622         if (count > 0)
01623                 return 1;
01624         else
01625                 return 0;
01626 }
01627 
01628 uint32 Actor::I_createActor(const uint8* args, unsigned int /*argsize*/)
01629 {
01630         ARG_UC_PTR(ptr);
01631         ARG_UINT16(shape);
01632         ARG_UINT16(frame);
01633 
01635 
01636         Actor* newactor = createActor(shape, frame);
01637         if (!newactor) {
01638                 perr << "I_createActor failed to create actor (" << shape
01639                          <<     ")." << std::endl;
01640                 return 0;
01641         }
01642         uint16 objID = newactor->getObjId();
01643 
01644         uint8 buf[2];
01645         buf[0] = static_cast<uint8>(objID);
01646         buf[1] = static_cast<uint8>(objID >> 8);
01647         UCMachine::get_instance()->assignPointer(ptr, buf, 2);
01648 
01649 #if 0
01650         perr << "I_createActor: created actor #" << objID << " with shape " << shape << std::endl;
01651 #endif
01652 
01653         return objID;
01654 }
01655 
01656 uint32 Actor::I_cSetActivity(const uint8* args, unsigned int /*argsize*/)
01657 {
01658         ARG_ACTOR_FROM_PTR(actor);
01659         ARG_UINT16(activity);
01660         if (!actor) return 0;
01661 
01662         return actor->cSetActivity(activity);
01663 }
01664 
01665 uint32 Actor::I_setAirWalkEnabled(const uint8* args, unsigned int /*argsize*/)
01666 {
01667         ARG_ACTOR_FROM_PTR(actor);
01668         ARG_UINT16(enabled);
01669         if (!actor) return 0;
01670 
01671         if (enabled)
01672                 actor->setActorFlag(ACT_AIRWALK);
01673         else
01674                 actor->clearActorFlag(ACT_AIRWALK);
01675 
01676         return 0;
01677 }
01678 
01679 
01680 uint32 Actor::I_getAirWalkEnabled(const uint8* args, unsigned int /*argsize*/)
01681 {
01682         ARG_ACTOR_FROM_PTR(actor);
01683         if (!actor) return 0;
01684 
01685         if (actor->getActorFlags() & ACT_AIRWALK)
01686                 return 1;
01687         else
01688                 return 0;
01689 }
01690 
01691 uint32 Actor::I_schedule(const uint8* args, unsigned int /*argsize*/)
01692 {
01693         ARG_ACTOR_FROM_PTR(actor);
01694         ARG_UINT32(time);
01695         if (!actor) return 0;
01696 
01697         return actor->schedule(time);
01698 }
01699 
01700 
01701 uint32 Actor::I_getEquip(const uint8* args, unsigned int /*argsize*/)
01702 {
01703         ARG_ACTOR_FROM_PTR(actor);
01704         ARG_UINT16(type);
01705         if (!actor) return 0;
01706 
01707         return actor->getEquip(type+1);
01708 }
01709 
01710 uint32 Actor::I_setEquip(const uint8* args, unsigned int /*argsize*/)
01711 {
01712         ARG_ACTOR_FROM_PTR(actor);
01713         ARG_UINT16(type);
01714         ARG_ITEM_FROM_ID(item);
01715         if (!actor) return 0;
01716         if (!item) return 0;
01717 
01718         if (!actor->setEquip(item, false))
01719                 return 0;
01720 
01721         // check it was added to the right slot
01722         assert(item->getZ() == type+1 || (item->getShape() == 529 && type == 6));
01723 
01724         return 1;
01725 }

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