void Script::moveCharacterToPlayer(uint16 characterId, uint16 v2, uint16 v3) { Resources &res = Resources::getReference(); Hotspot *playerHotspot = res.getActiveHotspot(PLAYER_ID); Hotspot *charHotspot = res.getActiveHotspot(characterId); assert(charHotspot); // If character in same room as player, then no need to do anything if (!charHotspot->currentActions().isEmpty() && (charHotspot->currentActions().top().roomNumber() == playerHotspot->roomNumber())) return; uint16 destRoom = playerHotspot->roomNumber(); const RoomTranslationRecord *rec; for (rec = &roomTranslations[0]; rec->srcRoom != 0; ++rec) { if (rec->srcRoom == destRoom) { destRoom = rec->destRoom; break; } } if (charHotspot->currentActions().isEmpty()) charHotspot->currentActions().addFront(DISPATCH_ACTION, destRoom); else charHotspot->currentActions().top().setRoomNumber(destRoom); }
void Script::remoteRoomViewSetup(uint16 v1, uint16 v2, uint16 v3) { Hotspot *player = Resources::getReference().getActiveHotspot(PLAYER_ID); player->setTickProc(NULL_TICK_PROC_ID); Resources::getReference().fieldList().setField(OLD_ROOM_NUMBER, player->roomNumber()); }
void FightsManager::enemyKilled() { Resources &res = Resources::getReference(); Hotspot *playerHotspot = res.getActiveHotspot(PLAYER_ID); FighterRecord &playerRec = getDetails(PLAYER_ID); playerHotspot->setTickProc(PLAYER_TICK_PROC_ID); playerRec.fwhits = GENERAL_MAGIC_ID; playerHotspot->resource()->colorOffset = 128; playerHotspot->setSize(32, 48); playerHotspot->resource()->width = 32; playerHotspot->resource()->height = 48; playerHotspot->setAnimationIndex(PLAYER_ANIM_INDEX); playerHotspot->setPosition(playerHotspot->x(), playerHotspot->y() + 5); playerHotspot->setDirection(LEFT); if (playerHotspot->roomNumber() == 6) { Dialog::show(0xc9f); HotspotData *axeHotspot = res.getHotspot(0x2738); axeHotspot->roomNumber = PLAYER_ID; axeHotspot->flags |= HOTSPOTFLAG_FOUND; // Prevent the weapon animation being drawn axeHotspot = res.getHotspot(0x440); axeHotspot->layer = 0; } }
void Script::setNewSupportData(uint16 index, uint16 hotspotId, uint16 v3) { Resources &res = Resources::getReference(); uint16 dataId = res.getCharOffset(index); CharacterScheduleEntry *entry = res.charSchedules().getEntry(dataId); Hotspot *h = res.getActiveHotspot(hotspotId); h->setBlockedFlag(false); h->currentActions().addFront(DISPATCH_ACTION, entry, h->roomNumber()); h->setActionCtr(0); }
void Script::barmanServe(uint16 v1, uint16 v2, uint16 v3) { Resources &res = Resources::getReference(); Hotspot *player = res.getActiveHotspot(PLAYER_ID); BarEntry &barEntry = res.barmanLists().getDetails(player->roomNumber()); for (int index = 0; index < NUM_SERVE_CUSTOMERS; ++index) { if (barEntry.customers[index].hotspotId == PLAYER_ID) { barEntry.customers[index].serveFlags |= 5; break; } } }
void Script::fixGoewin(uint16 v1, uint16 v2, uint16 v3) { Resources &res = Resources::getReference(); Hotspot *hotspot = res.getActiveHotspot(GOEWIN_ID); assert(hotspot); hotspot->setTickProc(STANDARD_CHARACTER_TICK_PROC); CharacterScheduleEntry *entry = res.charSchedules().getEntry(GOEWIN_STANDARD_SUPPORT_ID); assert(entry); hotspot->currentActions().clear(); hotspot->currentActions().addFront(DISPATCH_ACTION, entry, hotspot->roomNumber()); hotspot->setActions(hotspot->resource()->actions & ~(1 << (TELL - 1))); hotspot->setActionCtr(0); hotspot->setDelayCtr(0); hotspot->setCharacterMode(CHARMODE_NONE); }
void Script::setSupportData(uint16 hotspotId, uint16 index, uint16 v3) { Resources &res = Resources::getReference(); // WORKAROUND: In room #45, the script for the Skorl noticing you gets // the parameters back to front. If this the case, just ignore it if (index == CASTLE_SKORL_ID) return; uint16 dataId = res.getCharOffset(index); CharacterScheduleEntry *entry = res.charSchedules().getEntry(dataId); assert(entry != NULL); Hotspot *h = res.getActiveHotspot(hotspotId); assert(h); assert(!h->currentActions().isEmpty()); h->currentActions().pop(); h->currentActions().addFront(DISPATCH_ACTION, entry, h->roomNumber()); }
Hotspot *Resources::activateHotspot(uint16 hotspotId) { Resources &resources = Resources::getReference(); HotspotData *res = getHotspot(hotspotId); if (!res) return NULL; res->roomNumber &= 0x7fff; // clear any suppression bit in room # // Make sure that the hotspot isn't already active Hotspot *h = getActiveHotspot(hotspotId); if (h != NULL) return h; // If it's NPC with a schedule, then activate the schedule if ((res->npcScheduleId != 0) && (res->npcSchedule.isEmpty())) { CharacterScheduleEntry *entry = resources.charSchedules().getEntry(res->npcScheduleId); res->npcSchedule.addFront(DISPATCH_ACTION, entry, res->roomNumber); } // Check the script load flag if (res->scriptLoadFlag) { // Execute a script rather than doing a standard load Script::execute(res->loadOffset); } else { // Standard load bool loadFlag = true; uint16 talkIndex; switch (res->loadOffset) { case 1: // Copy protection check - since the game is freeware now, ignore it loadFlag = false; break; case 2: // Empty handler used to prevent loading hotspots that // are yet to be active (such as the straw fire) loadFlag = false; break; case 3: case 4: // Standard animation load break; case 5: // Custom loader used by the notice hotspot 42ah in room #20 talkIndex = _fieldList.getField(TALK_INDEX); if ((talkIndex < 8) || (talkIndex >= 14)) // Don't load hotspot loadFlag = false; else // Make the notice be on-screen res->startY = 85; break; case 6: // Torch in room #1 loadFlag = _fieldList.getField(TORCH_HIDE) == 0; break; default: // All others simply activate the hotspot warning("Hotspot %d uses unknown load offset index %d", res->hotspotId, res->loadOffset); } if (loadFlag) { Hotspot *hotspot = addHotspot(hotspotId); assert(hotspot); // Special post-load handling if (res->loadOffset == 3) hotspot->setPersistant(true); if (res->loadOffset == 5) hotspot->handleTalkDialog(); if (hotspotId == CASTLE_SKORL_ID) { // The Castle skorl has a default room #99, so it needs to be adjusted dynamically res->npcSchedule.clear(); CharacterScheduleEntry *entry = resources.charSchedules().getEntry(res->npcScheduleId); res->npcSchedule.addFront(DISPATCH_ACTION, entry, res->roomNumber); } if ((hotspotId == GOEWIN_ID) && (hotspot->roomNumber() == 39)) { // WORKAROUND: When you re-join Goewin in the caves, clear her schedule. This may prevent a // situation where you could close the left door, and she'd be permanently stuck trying to go // the next room on the left, since her old schedule still had her following your old path hotspot->currentActions().clear(); // Since she's no longer a follower, clear her start room field hotspot->setStartRoomNumber(0); } // TODO: Figure out why there's a room set in the animation decode for a range of characters, // particularly since it doesn't seem to match what happens in-game /* if ((hotspot->hotspotId() >= RATPOUCH_ID) && (hotspot->hotspotId() < FIRST_NONCHARACTER_ID) && (hotspot->roomNumber() < 42)) { // Start wandering characters off in room 24 hotspot->setRoomNumber(24); hotspot->setPosition(64, 116); _fieldList.wanderingCharsLoaded() = true; } */ return hotspot; } } return NULL; }