00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "MainActor.h"
00022 #include "TeleportEgg.h"
00023 #include "CurrentMap.h"
00024 #include "Process.h"
00025 #include "Kernel.h"
00026 #include "TeleportToEggProcess.h"
00027 #include "CameraProcess.h"
00028 #include "Animation.h"
00029 #include "GUIApp.h"
00030 #include "AvatarDeathProcess.h"
00031 #include "DelayProcess.h"
00032 #include "SettingManager.h"
00033 #include "CoreApp.h"
00034 #include "GameData.h"
00035 #include "WpnOvlayDat.h"
00036 #include "ShapeInfo.h"
00037 #include "AudioProcess.h"
00038 #include "World.h"
00039 #include "getObject.h"
00040 #include "UCList.h"
00041 #include "LoopScript.h"
00042 #include "AvatarGravityProcess.h"
00043 #include "MusicProcess.h"
00044
00045 #include "IDataSource.h"
00046 #include "ODataSource.h"
00047
00048
00049 DEFINE_RUNTIME_CLASSTYPE_CODE(MainActor,Actor);
00050
00051 MainActor::MainActor() : justTeleported(false), accumStr(0), accumDex(0),
00052 accumInt(0)
00053 {
00054
00055 }
00056
00057 MainActor::~MainActor()
00058 {
00059
00060 }
00061
00062 GravityProcess* MainActor::ensureGravityProcess()
00063 {
00064 AvatarGravityProcess* p = 0;
00065 if (gravitypid) {
00066 p = p_dynamic_cast<AvatarGravityProcess*>(
00067 Kernel::get_instance()->getProcess(gravitypid));
00068 } else {
00069 p = new AvatarGravityProcess(this, 0);
00070 Kernel::get_instance()->addProcess(p);
00071 p->init();
00072 }
00073 assert(p);
00074 return p;
00075 }
00076
00077 bool MainActor::CanAddItem(Item* item, bool checkwghtvol)
00078 {
00079 const unsigned int backpack_shape = 529;
00080
00081 if (!Actor::CanAddItem(item, checkwghtvol)) return false;
00082 if (item->getParent() == objid) return true;
00083
00084
00085
00086
00087 uint32 equiptype = item->getShapeInfo()->equiptype;
00088 bool backpack = (item->getShape() == backpack_shape);
00089
00090
00091 if (equiptype == ShapeInfo::SE_NONE && !backpack) return false;
00092
00093 std::list<Item*>::iterator iter;
00094 for (iter = contents.begin(); iter != contents.end(); ++iter)
00095 {
00096 uint32 cet = (*iter)->getShapeInfo()->equiptype;
00097 bool cbackpack = ((*iter)->getShape() == backpack_shape);
00098
00099
00100 if (cet == equiptype || (cbackpack && backpack)) return false;
00101 }
00102
00103 return true;
00104 }
00105
00106 bool MainActor::addItem(Item* item, bool checkwghtvol)
00107 {
00108 if (!Actor::addItem(item, checkwghtvol)) return false;
00109
00110 item->setFlag(FLG_EQUIPPED);
00111
00112 uint32 equiptype = item->getShapeInfo()->equiptype;
00113 item->setZ(equiptype);
00114
00115 return true;
00116 }
00117
00118 void MainActor::teleport(int mapnum, sint32 x, sint32 y, sint32 z)
00119 {
00120 World* world = World::get_instance();
00121
00122
00123 if (!world->switchMap(mapnum)) {
00124 perr << "MainActor::teleport(): switchMap() failed!" << std::endl;
00125 return;
00126 }
00127
00128 Actor::teleport(mapnum, x, y, z);
00129 justTeleported = true;
00130 }
00131
00132
00133
00134
00135 void MainActor::teleport(int mapnum, int teleport_id)
00136 {
00137 int oldmap = getMapNum();
00138 sint32 oldx, oldy, oldz;
00139 getLocation(oldx, oldy, oldz);
00140
00141 World* world = World::get_instance();
00142 CurrentMap* currentmap = world->getCurrentMap();
00143
00144 pout << "MainActor::teleport(): teleporting to map " << mapnum
00145 << ", egg " << teleport_id << std::endl;
00146
00147 setMapNum(mapnum);
00148
00149
00150 if (!world->switchMap(mapnum)) {
00151 perr << "MainActor::teleport(): switchMap() failed!" << std::endl;
00152 return;
00153 }
00154
00155
00156 TeleportEgg* egg = currentmap->findDestination(teleport_id);
00157 if (!egg) {
00158 perr << "MainActor::teleport(): destination egg not found!"
00159 << std::endl;
00160 teleport(oldmap, oldx, oldy, oldz);
00161 return;
00162 }
00163 sint32 x,y,z;
00164 egg->getLocation(x,y,z);
00165
00166 pout << "Found destination: " << x << "," << y << "," << z << std::endl;
00167 egg->dumpInfo();
00168
00169 Actor::teleport(mapnum, x, y, z);
00170 justTeleported = true;
00171 }
00172
00173 uint16 MainActor::getDefenseType()
00174 {
00175 uint16 type = 0;
00176
00177 std::list<Item*>::iterator iter;
00178 for (iter = contents.begin(); iter != contents.end(); ++iter)
00179 {
00180 uint32 frame = (*iter)->getFrame();
00181 ShapeInfo* si = (*iter)->getShapeInfo();
00182 if (si->armourinfo) {
00183 type |= si->armourinfo[frame].defense_type;
00184 }
00185 }
00186
00187 return type;
00188 }
00189
00190 uint32 MainActor::getArmourClass()
00191 {
00192 uint32 armour = 0;
00193
00194 std::list<Item*>::iterator iter;
00195 for (iter = contents.begin(); iter != contents.end(); ++iter)
00196 {
00197 uint32 frame = (*iter)->getFrame();
00198 ShapeInfo* si = (*iter)->getShapeInfo();
00199 if (si->armourinfo) {
00200 armour += si->armourinfo[frame].armour_class;
00201 }
00202 if (si->weaponinfo) {
00203 armour += si->weaponinfo->armour_bonus;
00204 }
00205 }
00206
00207 return armour;
00208 }
00209
00210 sint16 MainActor::getDefendingDex()
00211 {
00212 sint16 dex = getDex();
00213
00214 Item* weapon = getItem(getEquip(ShapeInfo::SE_WEAPON));
00215 if (weapon) {
00216 ShapeInfo* si = weapon->getShapeInfo();
00217 assert(si->weaponinfo);
00218 dex += si->weaponinfo->dex_defend_bonus;
00219 }
00220
00221 if (dex <= 0) dex = 1;
00222
00223 return dex;
00224 }
00225
00226 sint16 MainActor::getAttackingDex()
00227 {
00228 sint16 dex = getDex();
00229
00230 Item* weapon = getItem(getEquip(ShapeInfo::SE_WEAPON));
00231 if (weapon) {
00232 ShapeInfo* si = weapon->getShapeInfo();
00233 assert(si->weaponinfo);
00234 dex += si->weaponinfo->dex_attack_bonus;
00235 }
00236
00237 return dex;
00238 }
00239
00240 uint16 MainActor::getDamageType()
00241 {
00242 Item* weapon = getItem(getEquip(ShapeInfo::SE_WEAPON));
00243
00244 if (weapon) {
00245
00246
00247 ShapeInfo* si = weapon->getShapeInfo();
00248 assert(si->weaponinfo);
00249
00250 return si->weaponinfo->damage_type;
00251 }
00252
00253 return Actor::getDamageType();
00254 }
00255
00256 int MainActor::getDamageAmount()
00257 {
00258 int damage = 0;
00259
00260 if (getLastAnim() == Animation::kick) {
00261
00262
00263 int kick_bonus = 0;
00264 Item* legs = getItem(getEquip(ShapeInfo::SE_LEGS));
00265 if (legs) {
00266 ShapeInfo* si = legs->getShapeInfo();
00267 assert(si->armourinfo);
00268 kick_bonus = si->armourinfo[legs->getFrame()].kick_attack_bonus;
00269 }
00270
00271 damage = (std::rand() % (getStr()/2 + 1)) + kick_bonus;
00272
00273 return damage;
00274
00275 }
00276
00277 Item* weapon = getItem(getEquip(ShapeInfo::SE_WEAPON));
00278
00279
00280 if (weapon) {
00281
00282
00283 ShapeInfo* si = weapon->getShapeInfo();
00284 assert(si->weaponinfo);
00285
00286 int base = si->weaponinfo->base_damage;
00287 int mod = si->weaponinfo->damage_modifier;
00288
00289 damage = (std::rand() % (mod + 1)) + base + getStr()/5;
00290
00291 return damage;
00292 }
00293
00294
00295
00296 damage = (std::rand() % (getStr()/2 + 1)) + 1;
00297
00298 return damage;
00299 }
00300
00301 void MainActor::receiveHit(uint16 other, int dir, int damage,
00302 uint16 damage_type)
00303 {
00304 Actor::receiveHit(other, dir, damage, damage_type);
00305
00306 if (damage > 3 && other)
00307 {
00308
00309 }
00310 }
00311
00312 void MainActor::setInCombat()
00313 {
00314 setActorFlag(ACT_INCOMBAT);
00315 MusicProcess::get_instance()->playCombatMusic(98);
00316 }
00317
00318 void MainActor::clearInCombat()
00319 {
00320 clearActorFlag(ACT_INCOMBAT);
00321 MusicProcess::get_instance()->restoreMusic();
00322 }
00323
00324 ProcId MainActor::die(uint16 damageType)
00325 {
00326 ProcId animprocid = Actor::die(damageType);
00327
00328 GUIApp *app = p_dynamic_cast<GUIApp*>(GUIApp::get_instance());
00329 assert(app);
00330
00331 app->setAvatarInStasis(true);
00332
00333 Process* deathproc = new AvatarDeathProcess();
00334 Kernel::get_instance()->addProcess(deathproc);
00335
00336 Process* delayproc = new DelayProcess(30*5);
00337 Kernel::get_instance()->addProcess(delayproc);
00338
00339 Process* animproc = Kernel::get_instance()->getProcess(animprocid);
00340
00341 if (animproc)
00342 delayproc->waitFor(animproc);
00343
00344 deathproc->waitFor(delayproc);
00345
00346
00347
00348 return animprocid;
00349 }
00350
00351
00352 void MainActor::ConCmd_teleport(const Console::ArgvType &argv)
00353 {
00354 MainActor* mainactor = getMainActor();
00355 int curmap = mainactor->getMapNum();
00356
00357 switch (argv.size() - 1) {
00358 case 1:
00359 mainactor->teleport(curmap,
00360 strtol(argv[1].c_str(), 0, 0));
00361 break;
00362 case 2:
00363 mainactor->teleport(strtol(argv[1].c_str(), 0, 0),
00364 strtol(argv[2].c_str(), 0, 0));
00365 break;
00366 case 3:
00367 mainactor->teleport(curmap,
00368 strtol(argv[1].c_str(), 0, 0),
00369 strtol(argv[2].c_str(), 0, 0),
00370 strtol(argv[3].c_str(), 0, 0));
00371 break;
00372 case 4:
00373 mainactor->teleport(strtol(argv[1].c_str(), 0, 0),
00374 strtol(argv[2].c_str(), 0, 0),
00375 strtol(argv[3].c_str(), 0, 0),
00376 strtol(argv[4].c_str(), 0, 0));
00377 break;
00378 default:
00379 pout << "teleport usage:" << std::endl;
00380 pout << "teleport <mapnum> <x> <y> <z>: teleport to (x,y,z) on map mapnum" << std::endl;
00381 pout << "teleport <x> <y> <z>: teleport to (x,y,z) on current map" << std::endl;
00382 pout << "teleport <mapnum> <eggnum>: teleport to target egg eggnum on map mapnum" << std::endl;
00383 pout << "teleport <eggnum>: teleport to target egg eggnum on current map" << std::endl;
00384 break;
00385 }
00386 }
00387
00388 void MainActor::ConCmd_mark(const Console::ArgvType &argv)
00389 {
00390 if (argv.size() == 1) {
00391 pout << "Usage: mark <mark>: set named mark to this location" << std::endl;
00392 return;
00393 }
00394
00395 SettingManager* settings = SettingManager::get_instance();
00396 MainActor* mainactor = getMainActor();
00397 int curmap = mainactor->getMapNum();
00398 sint32 x,y,z;
00399 mainactor->getLocation(x,y,z);
00400
00401 Pentagram::istring confkey = "marks/" + argv[1];
00402 char buf[100];
00403 sprintf(buf, "%d %d %d %d", curmap, x, y, z);
00404
00405 settings->set(confkey, buf);
00406 settings->write();
00407
00408 pout << "Set mark \"" << argv[1].c_str() << "\" to " << buf << std::endl;
00409 }
00410
00411 void MainActor::ConCmd_recall(const Console::ArgvType &argv)
00412 {
00413 if (argv.size() == 1) {
00414 pout << "Usage: recall <mark>: recall to named mark" << std::endl;
00415 return;
00416 }
00417
00418 SettingManager* settings = SettingManager::get_instance();
00419 MainActor* mainactor = getMainActor();
00420 Pentagram::istring confkey = "marks/" + argv[1];
00421 std::string target;
00422 if (!settings->get(confkey, target)) {
00423 pout << "recall: no such mark" << std::endl;
00424 return;
00425 }
00426
00427 int t[4];
00428 int n = sscanf(target.c_str(), "%d%d%d%d", &t[0], &t[1], &t[2], &t[3]);
00429 if (n != 4) {
00430 pout << "recall: invalid mark" << std::endl;
00431 return;
00432 }
00433
00434 mainactor->teleport(t[0], t[1], t[2], t[3]);
00435 }
00436
00437 void MainActor::ConCmd_listmarks(const Console::ArgvType &argv)
00438 {
00439 SettingManager* settings = SettingManager::get_instance();
00440 std::vector<Pentagram::istring> marks;
00441 marks = settings->listDataKeys("marks");
00442 for (std::vector<Pentagram::istring>::iterator iter = marks.begin();
00443 iter != marks.end(); ++iter)
00444 {
00445 pout << (*iter) << std::endl;
00446 }
00447 }
00448
00449 void MainActor::ConCmd_maxstats(const Console::ArgvType &argv)
00450 {
00451 MainActor* mainactor = getMainActor();
00452
00453
00454 mainactor->setStr(25);
00455 mainactor->setDex(25);
00456 mainactor->setInt(25);
00457 mainactor->setHP(mainactor->getMaxHP());
00458 mainactor->setMana(mainactor->getMaxMana());
00459
00460 AudioProcess* audioproc = AudioProcess::get_instance();
00461 if (audioproc) audioproc->playSFX(0x36, 0x60, 1, 0);
00462 }
00463
00464 void MainActor::ConCmd_heal(const Console::ArgvType &argv)
00465 {
00466 MainActor* mainactor = getMainActor();
00467
00468 mainactor->setHP(mainactor->getMaxHP());
00469 mainactor->setMana(mainactor->getMaxMana());
00470 }
00471
00472
00473 void MainActor::accumulateStr(int n)
00474 {
00475
00476 if (strength == 25) return;
00477
00478 accumStr += n;
00479 if (accumStr >= 650 || std::rand() % (650 - accumStr) == 0) {
00480 strength++;
00481 accumStr = 0;
00482 AudioProcess* audioproc = AudioProcess::get_instance();
00483 if (audioproc) audioproc->playSFX(0x36, 0x60, 1, 0);
00484 pout << "Gained strength!" << std::endl;
00485 }
00486 }
00487
00488 void MainActor::accumulateDex(int n)
00489 {
00490
00491 if (dexterity == 25) return;
00492
00493 accumDex += n;
00494 if (accumDex >= 650 || std::rand() % (650 - accumDex) == 0) {
00495 dexterity++;
00496 accumDex = 0;
00497 AudioProcess* audioproc = AudioProcess::get_instance();
00498 if (audioproc) audioproc->playSFX(0x36, 0x60, 1, 0);
00499 pout << "Gained dexterity!" << std::endl;
00500 }
00501 }
00502
00503 void MainActor::accumulateInt(int n)
00504 {
00505
00506 if (intelligence == 25) return;
00507
00508 accumInt += n;
00509 if (accumInt >= 650 || std::rand() % (650 - accumInt) == 0) {
00510 intelligence++;
00511 accumInt = 0;
00512 AudioProcess* audioproc = AudioProcess::get_instance();
00513 if (audioproc) audioproc->playSFX(0x36, 0x60, 1, 0);
00514 pout << "Gained intelligence!" << std::endl;
00515 }
00516 }
00517
00518 void MainActor::getWeaponOverlay(const WeaponOverlayFrame*& frame,
00519 uint32& shape)
00520 {
00521 shape = 0;
00522 frame = 0;
00523
00524 if (!isInCombat() && lastanim != Animation::unreadyWeapon) return;
00525
00526 ObjId weaponid = getEquip(ShapeInfo::SE_WEAPON);
00527 Item* weapon = getItem(weaponid);
00528 if (!weapon) return;
00529
00530 ShapeInfo* shapeinfo = weapon->getShapeInfo();
00531 if (!shapeinfo) return;
00532
00533 WeaponInfo* weaponinfo = shapeinfo->weaponinfo;
00534 if (!weaponinfo) return;
00535
00536 shape = weaponinfo->overlay_shape;
00537
00538 WpnOvlayDat* wpnovlay = GameData::get_instance()->getWeaponOverlay();
00539 frame = wpnovlay->getOverlayFrame(lastanim, weaponinfo->overlay_type,
00540 direction, animframe);
00541
00542 if (frame == 0) shape = 0;
00543 }
00544
00545 void MainActor::saveData(ODataSource* ods)
00546 {
00547 Actor::saveData(ods);
00548 uint8 jt = justTeleported ? 1 : 0;
00549 ods->write1(jt);
00550 ods->write4(accumStr);
00551 ods->write4(accumDex);
00552 ods->write4(accumInt);
00553 uint8 namelength = static_cast<uint8>(name.size());
00554 ods->write1(namelength);
00555 for (unsigned int i = 0; i < namelength; ++i)
00556 ods->write1(static_cast<uint8>(name[i]));
00557
00558 }
00559
00560 bool MainActor::loadData(IDataSource* ids, uint32 version)
00561 {
00562 if (!Actor::loadData(ids, version)) return false;
00563
00564 justTeleported = (ids->read1() != 0);
00565 accumStr = static_cast<sint32>(ids->read4());
00566 accumDex = static_cast<sint32>(ids->read4());
00567 accumInt = static_cast<sint32>(ids->read4());
00568
00569 uint8 namelength = ids->read1();
00570 name.resize(namelength);
00571 for (unsigned int i = 0; i < namelength; ++i)
00572 name[i] = ids->read1();
00573
00574 return true;
00575 }
00576
00577 uint32 MainActor::I_teleportToEgg(const uint8* args, unsigned int )
00578 {
00579 ARG_UINT16(mapnum);
00580 ARG_UINT16(teleport_id);
00581 ARG_UINT16(unknown);
00582
00583 return Kernel::get_instance()->addProcess(
00584 new TeleportToEggProcess(mapnum, teleport_id));
00585 }
00586
00587 uint32 MainActor::I_accumulateStrength(const uint8* args,
00588 unsigned int )
00589 {
00590 ARG_SINT16(n);
00591 MainActor* av = getMainActor();
00592 av->accumulateStr(n);
00593
00594 return 0;
00595 }
00596
00597 uint32 MainActor::I_accumulateDexterity(const uint8* args,
00598 unsigned int )
00599 {
00600 ARG_SINT16(n);
00601 MainActor* av = getMainActor();
00602 av->accumulateDex(n);
00603
00604 return 0;
00605 }
00606
00607 uint32 MainActor::I_accumulateIntelligence(const uint8* args,
00608 unsigned int )
00609 {
00610 ARG_SINT16(n);
00611 MainActor* av = getMainActor();
00612 av->accumulateInt(n);
00613
00614 return 0;
00615 }
00616
00617 uint32 MainActor::I_clrAvatarInCombat(const uint8* ,
00618 unsigned int )
00619 {
00620 MainActor* av = getMainActor();
00621 av->clearInCombat();
00622
00623 return 0;
00624 }
00625
00626 uint32 MainActor::I_setAvatarInCombat(const uint8* ,
00627 unsigned int )
00628 {
00629 MainActor* av = getMainActor();
00630 av->setInCombat();
00631
00632 return 0;
00633 }
00634
00635 uint32 MainActor::I_isAvatarInCombat(const uint8* ,
00636 unsigned int )
00637 {
00638 MainActor* av = getMainActor();
00639 if (av->isInCombat())
00640 return 1;
00641 else
00642 return 0;
00643 }
00644
00645 void MainActor::ConCmd_name(const Console::ArgvType &argv)
00646 {
00647 MainActor* av = getMainActor();
00648 if (argv.size() > 1)
00649 av->setName(argv[1]);
00650
00651 pout << "MainActor::name = \"" << av->getName() << "\"" << std::endl;
00652 }
00653
00654 void MainActor::ConCmd_useBackpack(const Console::ArgvType &argv)
00655 {
00656 if (GUIApp::get_instance()->isAvatarInStasis())
00657 {
00658 pout << "Can't: avatarInStasis" << std::endl;
00659 return;
00660 }
00661 MainActor* av = getMainActor();
00662 Item* backpack = getItem(av->getEquip(7));
00663 if (backpack)
00664 backpack->callUsecodeEvent_use();
00665 }
00666
00667 void MainActor::ConCmd_useInventory(const Console::ArgvType &argv)
00668 {
00669 if (GUIApp::get_instance()->isAvatarInStasis())
00670 {
00671 pout << "Can't: avatarInStasis" << std::endl;
00672 return;
00673 }
00674 MainActor* av = getMainActor();
00675 av->callUsecodeEvent_use();
00676 }
00677
00678 void MainActor::useInventoryItem(uint32 shapenum)
00679 {
00680 if (GUIApp::get_instance()->isAvatarInStasis())
00681 {
00682 pout << "Can't: avatarInStasis" << std::endl;
00683 return;
00684 }
00685 LOOPSCRIPT(script, LS_SHAPE_EQUAL(shapenum));
00686 UCList uclist(2);
00687 this->containerSearch(&uclist, script, sizeof(script), true);
00688 if (uclist.getSize() < 1)
00689 return;
00690
00691 uint16 objid = uclist.getuint16(0);
00692 Item* item = getItem(objid);
00693 item->callUsecodeEvent_use();
00694
00695 }
00696
00697 void MainActor::ConCmd_useRecall(const Console::ArgvType &argv)
00698 {
00699 MainActor* av = getMainActor();
00700 av->useInventoryItem(833);
00701 }
00702
00703 void MainActor::ConCmd_useBedroll(const Console::ArgvType &argv)
00704 {
00705 MainActor* av = getMainActor();
00706 av->useInventoryItem(534);
00707 }
00708
00709 void MainActor::ConCmd_useKeyring(const Console::ArgvType &argv)
00710 {
00711 MainActor* av = getMainActor();
00712 av->useInventoryItem(79);
00713 }
00714
00715 void MainActor::ConCmd_toggleCombat(const Console::ArgvType &argv)
00716 {
00717 if (GUIApp::get_instance()->isAvatarInStasis())
00718 {
00719 pout << "Can't: avatarInStasis" << std::endl;
00720 return;
00721 }
00722 MainActor* av = getMainActor();
00723 av->toggleInCombat();
00724 }
00725
00726 void MainActor::ConCmd_toggleInvincibility(const Console::ArgvType &argv)
00727 {
00728 MainActor* av = getMainActor();
00729
00730 if (av->getActorFlags() & Actor::ACT_INVINCIBLE) {
00731
00732 av->clearActorFlag(Actor::ACT_INVINCIBLE);
00733 pout << "Avatar is no longer invincible." << std::endl;
00734
00735
00736 } else {
00737
00738 av->setActorFlag(Actor::ACT_INVINCIBLE);
00739 pout << "Avatar invincible." << std::endl;
00740
00741 }
00742 }
00743
00744