00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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);
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
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
00150 if (ti.chance < 0.999 &&
00151 (static_cast<double>(std::rand()) / RAND_MAX) > ti.chance)
00152 {
00153 continue;
00154 }
00155
00156
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
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
00182 item = ItemFactory::createItem(s,
00183 0,
00184 count,
00185 Item::FLG_DISPOSABLE,
00186 0,
00187 0,
00188 0, true);
00189 item->moveToContainer(this);
00190 item->randomGumpLocation();
00191 break;
00192 }
00193 } else if (ti.special == "sorcfocus") {
00194
00195 int shape = 397;
00196 int frame;
00197 uint16 quality;
00198
00199 if (std::rand() % 10 < 8)
00200 {
00201
00202 if (std::rand() % 10 < 4) {
00203
00204 frame = 0;
00205 quality = 3 + (std::rand() % 4) +
00206 ((1 + (std::rand()%4))<<8);
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
00222 if (std::rand() % 10 < 2) {
00223
00224 frame = 3;
00225 quality = 3 + (std::rand() % 4) +
00226 ((1 + (std::rand()%7))<<8);
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
00242 if (std::rand() % 10 < 5) {
00243
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
00251
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
00269 if (std::rand() % 10 < 2) {
00270
00271 frame = 9;
00272 quality = 1 + (std::rand() % 2) +
00273 ((10 + (std::rand()%2))<<8);
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
00294
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
00306 item = ItemFactory::createItem(shape,
00307 0,
00308 count,
00309 Item::FLG_DISPOSABLE,
00310 0,
00311 0,
00312 0, true);
00313 item->moveToContainer(this);
00314 item->randomGumpLocation();
00315 item->callUsecodeEvent_combine();
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
00326 for (int i = 0; i < count; ++i) {
00327
00328 int n = std::rand() % ti.shapes.size();
00329 uint32 shape = ti.shapes[n];
00330
00331
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
00347 item = ItemFactory::createItem(shape,
00348 frame,
00349 qual,
00350 Item::FLG_DISPOSABLE,
00351 0,
00352 0,
00353 0, true);
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);
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
00378 if (equiptype == ShapeInfo::SE_NONE && !backpack) return false;
00379
00380
00381
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
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)))
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
00427 setMapNum(newmapnum);
00428
00429
00430 moveToEtherealVoid();
00431
00432
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
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
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);
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:
00544 Kernel::get_instance()->addProcess(new LoiterProcess(this));
00545 return Kernel::get_instance()->addProcess(new DelayProcess(1));
00546 break;
00547 case 1:
00548 setInCombat();
00549 return 0;
00550 case 2:
00551
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;
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
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
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
00668
00669 if (getActorFlags() & ACT_WITHSTANDDEATH) {
00670
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
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
00690 doAnim(Animation::fallBackwards, 8);
00691
00692
00693 return;
00694 }
00695
00696
00697 fallingprocid = killAllButFallAnims(false);
00698 }
00699
00700
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);
00714 else
00715 sfx = 20 + (std::rand() % 3);
00716 AudioProcess* audioproc = AudioProcess::get_instance();
00717 if (audioproc) audioproc->playSFX(sfx, 0x60, objid, 0);
00718 return;
00719 }
00720
00721
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
00736 }
00737 }
00738
00739 if (damage && !fallingprocid) {
00740 ProcId anim1pid = doAnim(Animation::stumbleBackwards, dir);
00741 ProcId anim2pid;
00742 if (isInCombat())
00743
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);
00766 #endif
00767
00768 if (!animprocid)
00769 animprocid = doAnim(Animation::die, getDir());
00770
00771
00772 MainActor* avatar = getMainActor();
00773
00774 if (getEnemyAlignment() & avatar->getAlignment()) {
00775 if (avatar->isInCombat()) {
00776
00777 MusicProcess::get_instance()->playCombatMusic(109);
00778
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
00793
00794 pout << "Actor::die: scheduling resurrection" << std::endl;
00795
00796 int timeout = ((std::rand() % 25) + 5) * 30;
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
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,
00827 Item::FLG_FAST_ONLY,
00828 0,
00829 0,
00830 0, true
00831 );
00832 piece->move(x - 128 + 32*(std::rand()%6),
00833 y - 128 + 32*(std::rand()%6),
00834 z + std::rand()%8 );
00835 piece->hurl(-25 + (std::rand()%50),
00836 -25 + (std::rand()%50),
00837 10 + (std::rand()%10),
00838 4);
00839 }
00840 }
00841
00842 return animprocid;
00843 }
00844
00845 void Actor::killAllButCombatProcesses()
00846 {
00847
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
00874 kernel->killProcessesNotOfType(objid, 0xF0, true);
00875 } else {
00876
00877 killAllButCombatProcesses();
00878 }
00879
00880
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
00913 damage_type &= ~(defense_type & ~(WeaponInfo::DMG_MAGIC |
00914 WeaponInfo::DMG_UNDEAD |
00915 WeaponInfo::DMG_PIERCE));
00916
00917
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
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;
00933 }
00934 }
00935
00936 if ((damage_type & WeaponInfo::DMG_UNDEAD) &&
00937 (defense_type & WeaponInfo::DMG_UNDEAD))
00938 {
00939 damage *= 2;
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;
00948 }
00949 } else {
00950 damage = 0;
00951 }
00952
00953
00954 if (damage && !(damage_type & WeaponInfo::DMG_PIERCE) && !slayer)
00955 {
00956
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;
00967
00968 if (getActorFlags() & ACT_STUNNED)
00969 ACmod /= 2;
00970
00971 if (ACmod > 100) ACmod = 100;
00972
00973
00974 damage = ((100 - ACmod) * damage) / 100;
00975
00976 if (damage < 0) damage = 0;
00977 }
00978
00979
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
00995
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);
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
01030 Kernel::get_instance()->killProcesses(getObjId(), 6, true);
01031
01032
01033 ProcId castproc = callUsecodeEvent_cast(0);
01034
01035 CombatProcess* cp = new CombatProcess(this);
01036 Kernel::get_instance()->addProcess(cp);
01037
01038
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);
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
01071
01072
01073
01074
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
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
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 )
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 )
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 )
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 )
01199 {
01200 ARG_ACTOR_FROM_PTR(actor);
01201 ARG_UINT16(anim);
01202 ARG_UINT16(dir);
01203 ARG_UINT16(unk1);
01204 ARG_UINT16(unk2);
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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);
01556 Kernel::get_instance()->addProcess(delayproc);
01557
01558 Process* clearproc = new ClearFeignDeathProcess(actor);
01559 Kernel::get_instance()->addProcess(clearproc);
01560
01561
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 )
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 )
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 )
01593 {
01594 ARG_ACTOR_FROM_PTR(actor);
01595 ARG_UINT16(x);
01596 ARG_UINT16(y);
01597 ARG_UINT16(z);
01598 ARG_NULL16();
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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
01722 assert(item->getZ() == type+1 || (item->getShape() == 529 && type == 6));
01723
01724 return 1;
01725 }