648 lines
19 KiB
Plaintext
648 lines
19 KiB
Plaintext
// Pet system
|
|
// Handles pet acquisition, loyalty, feeding, retrieval, and combat support
|
|
|
|
bool petActive = false;
|
|
string petSoundPath = "";
|
|
string petType = "";
|
|
string petGender = "";
|
|
int petLoyalty = 0;
|
|
bool petOut = false;
|
|
|
|
timer petAttackTimer;
|
|
timer petRetrieveTimer;
|
|
|
|
string[] petEventMessages;
|
|
string[] petEventSounds;
|
|
int[] petEventPositions;
|
|
int petEventSoundHandle = -1;
|
|
|
|
const int PET_TRAVEL_NONE = 0;
|
|
const int PET_TRAVEL_ATTACK = 1;
|
|
const int PET_TRAVEL_RETRIEVE = 2;
|
|
|
|
bool petTravelActive = false;
|
|
int petTravelAction = PET_TRAVEL_NONE;
|
|
int petTravelStartPos = 0;
|
|
int petTravelTargetPos = -1;
|
|
int petTravelTargetKind = -1;
|
|
string petTravelTargetLabel = "";
|
|
int petTravelDurationMs = 0;
|
|
int petTravelSoundHandle = -1;
|
|
timer petTravelTimer;
|
|
|
|
string[] petSoundPaths;
|
|
bool petSoundsInitialized = false;
|
|
|
|
string normalize_pet_path(const string&in path) {
|
|
return path.replace("\\", "/", true);
|
|
}
|
|
|
|
string collapse_pet_spaces(const string&in text) {
|
|
string result = text;
|
|
while (result.find_first(" ") > -1) {
|
|
result = result.replace(" ", " ", true);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void gather_pet_sound_files(const string&in basePath, string[]@ outFiles) {
|
|
string[]@ files = find_files(basePath + "/*.ogg");
|
|
if (@files !is null) {
|
|
for (uint i = 0; i < files.length(); i++) {
|
|
outFiles.insert_last(basePath + "/" + files[i]);
|
|
}
|
|
}
|
|
|
|
string[]@ folders = find_directories(basePath + "/*");
|
|
if (@folders !is null) {
|
|
for (uint i = 0; i < folders.length(); i++) {
|
|
gather_pet_sound_files(basePath + "/" + folders[i], outFiles);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool sort_pet_sound_paths(const string &in a, const string &in b) {
|
|
return a.lower() < b.lower();
|
|
}
|
|
|
|
void init_pet_sounds() {
|
|
if (petSoundsInitialized) return;
|
|
petSoundsInitialized = true;
|
|
petSoundPaths.resize(0);
|
|
if (!directory_exists("sounds/pets")) return;
|
|
gather_pet_sound_files("sounds/pets", petSoundPaths);
|
|
if (petSoundPaths.length() > 1) {
|
|
petSoundPaths.sort(sort_pet_sound_paths);
|
|
}
|
|
}
|
|
|
|
string get_pet_name_from_sound_path(const string&in soundPath) {
|
|
string normalizedPath = normalize_pet_path(soundPath);
|
|
int slashPos = normalizedPath.find_last_of("/");
|
|
string name = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath;
|
|
string lowerName = name.lower();
|
|
if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".ogg") {
|
|
name = name.substr(0, name.length() - 4);
|
|
}
|
|
name = name.replace("_", " ", true);
|
|
name = name.replace("-", " ", true);
|
|
name = collapse_pet_spaces(name);
|
|
name = name.lower();
|
|
name.trim_whitespace_this();
|
|
if (name.length() == 0) return "Pet";
|
|
string first = name.substr(0, 1).upper();
|
|
if (name.length() == 1) return first;
|
|
return first + name.substr(1);
|
|
}
|
|
|
|
string get_pet_sound_for_name(const string&in petName) {
|
|
init_pet_sounds();
|
|
string target = petName.lower();
|
|
for (uint i = 0; i < petSoundPaths.length(); i++) {
|
|
string normalizedPath = normalize_pet_path(petSoundPaths[i]);
|
|
int slashPos = normalizedPath.find_last_of("/");
|
|
string fileName = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath;
|
|
string lowerName = fileName.lower();
|
|
if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".ogg") {
|
|
lowerName = lowerName.substr(0, lowerName.length() - 4);
|
|
}
|
|
if (lowerName == target) {
|
|
return petSoundPaths[i];
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
int get_pet_food_personal_total() {
|
|
return get_personal_count(ITEM_MEAT)
|
|
+ get_personal_count(ITEM_SMOKED_FISH)
|
|
+ get_personal_count(ITEM_FISH)
|
|
+ get_personal_count(ITEM_BASKET_FOOD);
|
|
}
|
|
|
|
int get_pet_food_storage_total() {
|
|
return get_storage_count(ITEM_MEAT)
|
|
+ get_storage_count(ITEM_SMOKED_FISH)
|
|
+ get_storage_count(ITEM_FISH)
|
|
+ get_storage_count(ITEM_BASKET_FOOD);
|
|
}
|
|
|
|
bool has_pet_food_available() {
|
|
return get_pet_food_personal_total() + get_pet_food_storage_total() > 0;
|
|
}
|
|
|
|
bool consume_pet_food() {
|
|
if (get_personal_count(ITEM_MEAT) > 0) {
|
|
add_personal_count(ITEM_MEAT, -1);
|
|
return true;
|
|
}
|
|
if (get_personal_count(ITEM_SMOKED_FISH) > 0) {
|
|
add_personal_count(ITEM_SMOKED_FISH, -1);
|
|
return true;
|
|
}
|
|
if (get_personal_count(ITEM_FISH) > 0) {
|
|
pop_personal_fish_weight();
|
|
add_personal_count(ITEM_FISH, -1);
|
|
return true;
|
|
}
|
|
if (get_personal_count(ITEM_BASKET_FOOD) > 0) {
|
|
add_personal_count(ITEM_BASKET_FOOD, -1);
|
|
return true;
|
|
}
|
|
if (get_storage_count(ITEM_MEAT) > 0) {
|
|
add_storage_count(ITEM_MEAT, -1);
|
|
return true;
|
|
}
|
|
if (get_storage_count(ITEM_SMOKED_FISH) > 0) {
|
|
add_storage_count(ITEM_SMOKED_FISH, -1);
|
|
return true;
|
|
}
|
|
if (get_storage_count(ITEM_FISH) > 0) {
|
|
pop_storage_fish_weight();
|
|
add_storage_count(ITEM_FISH, -1);
|
|
return true;
|
|
}
|
|
if (get_storage_count(ITEM_BASKET_FOOD) > 0) {
|
|
add_storage_count(ITEM_BASKET_FOOD, -1);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void queue_pet_event(const string&in message, int soundPos = -1) {
|
|
if (!petActive) return;
|
|
if (message.length() == 0) return;
|
|
petEventMessages.insert_last(message);
|
|
petEventSounds.insert_last(petSoundPath);
|
|
petEventPositions.insert_last(soundPos);
|
|
}
|
|
|
|
void update_pet_events() {
|
|
if (petEventMessages.length() == 0) {
|
|
petEventSoundHandle = -1;
|
|
return;
|
|
}
|
|
|
|
if (petEventSoundHandle != -1) {
|
|
if (p.sound_is_active(petEventSoundHandle)) {
|
|
return;
|
|
}
|
|
string message = petEventMessages[0];
|
|
petEventMessages.remove_at(0);
|
|
petEventSounds.remove_at(0);
|
|
petEventPositions.remove_at(0);
|
|
petEventSoundHandle = -1;
|
|
speak_with_history(message, true);
|
|
return;
|
|
}
|
|
|
|
string soundPath = petEventSounds[0];
|
|
int soundPos = petEventPositions[0];
|
|
if (soundPath != "" && file_exists(soundPath)) {
|
|
if (soundPos >= 0) {
|
|
petEventSoundHandle = play_1d_with_volume_step(soundPath, x, soundPos, false, PLAYER_WEAPON_SOUND_VOLUME_STEP);
|
|
} else {
|
|
petEventSoundHandle = p.play_stationary(soundPath, false);
|
|
}
|
|
if (petEventSoundHandle != -1) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
string message = petEventMessages[0];
|
|
petEventMessages.remove_at(0);
|
|
petEventSounds.remove_at(0);
|
|
petEventPositions.remove_at(0);
|
|
speak_with_history(message, true);
|
|
}
|
|
|
|
void reset_pet_state() {
|
|
petActive = false;
|
|
petSoundPath = "";
|
|
petType = "";
|
|
petGender = "";
|
|
petLoyalty = 0;
|
|
petOut = false;
|
|
petEventMessages.resize(0);
|
|
petEventSounds.resize(0);
|
|
petEventPositions.resize(0);
|
|
petEventSoundHandle = -1;
|
|
petTravelActive = false;
|
|
petTravelAction = PET_TRAVEL_NONE;
|
|
petTravelStartPos = 0;
|
|
petTravelTargetPos = -1;
|
|
petTravelTargetKind = -1;
|
|
petTravelTargetLabel = "";
|
|
petTravelDurationMs = 0;
|
|
safe_destroy_sound(petTravelSoundHandle);
|
|
petTravelSoundHandle = -1;
|
|
petAttackTimer.restart();
|
|
petRetrieveTimer.restart();
|
|
petTravelTimer.restart();
|
|
}
|
|
|
|
void pet_leave() {
|
|
string oldPet = petType;
|
|
reset_pet_state();
|
|
if (oldPet != "") {
|
|
speak_with_history(oldPet + " leaves.", true);
|
|
}
|
|
}
|
|
|
|
void clamp_pet_loyalty() {
|
|
if (petLoyalty < 0) petLoyalty = 0;
|
|
if (petLoyalty > PET_LOYALTY_MAX) petLoyalty = PET_LOYALTY_MAX;
|
|
}
|
|
|
|
void adjust_pet_loyalty(int delta) {
|
|
if (!petActive) return;
|
|
petLoyalty += delta;
|
|
clamp_pet_loyalty();
|
|
if (petLoyalty <= 0) {
|
|
pet_leave();
|
|
}
|
|
}
|
|
|
|
void check_pet_call_key() {
|
|
if (!key_pressed(KEY_SPACE)) return;
|
|
if (!petActive) {
|
|
speak_with_history("No pet.", true);
|
|
return;
|
|
}
|
|
if (petOut) {
|
|
petOut = false;
|
|
stop_pet_travel();
|
|
speak_with_history("Pet called back.", true);
|
|
return;
|
|
}
|
|
petOut = true;
|
|
if (file_exists("sounds/pets/call_pet.ogg")) {
|
|
p.play_stationary("sounds/pets/call_pet.ogg", false);
|
|
}
|
|
}
|
|
|
|
void adopt_pet(const string&in soundPath) {
|
|
petActive = true;
|
|
petSoundPath = soundPath;
|
|
petType = get_pet_name_from_sound_path(soundPath);
|
|
petGender = (random(0, 1) == 0) ? "Male" : "Female";
|
|
petLoyalty = PET_START_LOYALTY;
|
|
petOut = false;
|
|
petAttackTimer.restart();
|
|
petRetrieveTimer.restart();
|
|
petTravelTimer.restart();
|
|
speak_with_history("A " + petType + " joins you.", true);
|
|
}
|
|
|
|
void stop_pet_travel() {
|
|
petTravelActive = false;
|
|
petTravelAction = PET_TRAVEL_NONE;
|
|
petTravelStartPos = 0;
|
|
petTravelTargetPos = -1;
|
|
petTravelTargetKind = -1;
|
|
petTravelTargetLabel = "";
|
|
petTravelDurationMs = 0;
|
|
safe_destroy_sound(petTravelSoundHandle);
|
|
petTravelSoundHandle = -1;
|
|
}
|
|
|
|
int get_pet_travel_duration_ms(int targetPos) {
|
|
int distance = abs(targetPos - x);
|
|
int duration = distance * PET_MOVE_SPEED;
|
|
if (duration < PET_TRAVEL_MIN_MS) duration = PET_TRAVEL_MIN_MS;
|
|
return duration;
|
|
}
|
|
|
|
void start_pet_travel_attack(int targetPos, const string&in targetLabel, int targetKind) {
|
|
stop_pet_travel();
|
|
petTravelActive = true;
|
|
petTravelAction = PET_TRAVEL_ATTACK;
|
|
petTravelStartPos = x;
|
|
petTravelTargetPos = targetPos;
|
|
petTravelTargetLabel = targetLabel;
|
|
petTravelTargetKind = targetKind;
|
|
petTravelDurationMs = get_pet_travel_duration_ms(targetPos);
|
|
petTravelTimer.restart();
|
|
|
|
if (petSoundPath != "" && file_exists(petSoundPath)) {
|
|
petTravelSoundHandle = play_1d_with_volume_step(
|
|
petSoundPath,
|
|
x,
|
|
petTravelStartPos,
|
|
true,
|
|
PLAYER_WEAPON_SOUND_VOLUME_STEP
|
|
);
|
|
}
|
|
}
|
|
|
|
void start_pet_travel_retrieve(int targetPos) {
|
|
stop_pet_travel();
|
|
petTravelActive = true;
|
|
petTravelAction = PET_TRAVEL_RETRIEVE;
|
|
petTravelStartPos = x;
|
|
petTravelTargetPos = targetPos;
|
|
petTravelDurationMs = get_pet_travel_duration_ms(targetPos);
|
|
petTravelTimer.restart();
|
|
}
|
|
|
|
void update_pet_travel() {
|
|
if (!petTravelActive) return;
|
|
if (petTravelDurationMs < 1) petTravelDurationMs = 1;
|
|
|
|
int elapsed = petTravelTimer.elapsed;
|
|
float progress = float(elapsed) / float(petTravelDurationMs);
|
|
if (progress > 1.0f) progress = 1.0f;
|
|
|
|
int travel = int(float(petTravelTargetPos - petTravelStartPos) * progress);
|
|
int currentPos = petTravelStartPos + travel;
|
|
if (petTravelSoundHandle != -1) {
|
|
p.update_sound_1d(petTravelSoundHandle, currentPos);
|
|
}
|
|
|
|
if (elapsed < petTravelDurationMs) return;
|
|
|
|
safe_destroy_sound(petTravelSoundHandle);
|
|
petTravelSoundHandle = -1;
|
|
|
|
if (petTravelAction == PET_TRAVEL_ATTACK) {
|
|
int damage = BOW_DAMAGE_MAX;
|
|
bool hit = false;
|
|
if (petTravelTargetKind == 0) {
|
|
hit = damage_bandit_at(petTravelTargetPos, damage);
|
|
} else if (petTravelTargetKind == 1) {
|
|
hit = damage_undead_at(petTravelTargetPos, damage);
|
|
} else if (petTravelTargetKind == 2) {
|
|
hit = damage_boar_at(petTravelTargetPos, damage);
|
|
}
|
|
if (hit) {
|
|
queue_pet_event("Your " + petType + " attacks the " + petTravelTargetLabel + ".", petTravelTargetPos);
|
|
}
|
|
adjust_pet_loyalty(-PET_LOYALTY_ACTION_COST);
|
|
} else if (petTravelAction == PET_TRAVEL_RETRIEVE) {
|
|
WorldDrop@ drop = get_drop_at(petTravelTargetPos);
|
|
if (drop !is null) {
|
|
string message = "";
|
|
if (try_pet_pickup_world_drop(drop, message)) {
|
|
remove_drop_at(drop.position);
|
|
queue_pet_event(message);
|
|
petOut = false;
|
|
}
|
|
}
|
|
adjust_pet_loyalty(-PET_LOYALTY_ACTION_COST);
|
|
}
|
|
|
|
stop_pet_travel();
|
|
}
|
|
|
|
bool run_pet_offer_menu(const string&in soundPath, const string&in reasonText) {
|
|
if (petActive) return false;
|
|
if (soundPath == "" || !file_exists(soundPath)) return false;
|
|
if (!has_pet_food_available()) return false;
|
|
|
|
string petName = get_pet_name_from_sound_path(soundPath);
|
|
string prompt = "A friendly looking " + petName + " begs for food. Accept?";
|
|
if (reasonText != "") {
|
|
prompt += " " + reasonText;
|
|
}
|
|
|
|
string[] options;
|
|
options.insert_last("Yes");
|
|
options.insert_last("No");
|
|
int selection = 0;
|
|
|
|
speak_with_history(prompt + " " + options[selection], true);
|
|
|
|
while (true) {
|
|
wait(5);
|
|
if (menu_background_tick()) {
|
|
return false;
|
|
}
|
|
if (key_pressed(KEY_ESCAPE)) {
|
|
speak_with_history("Declined.", true);
|
|
return false;
|
|
}
|
|
if (key_pressed(KEY_DOWN)) {
|
|
play_menu_move_sound();
|
|
selection++;
|
|
if (selection >= int(options.length())) selection = 0;
|
|
speak_with_history(options[selection], true);
|
|
}
|
|
if (key_pressed(KEY_UP)) {
|
|
play_menu_move_sound();
|
|
selection--;
|
|
if (selection < 0) selection = int(options.length()) - 1;
|
|
speak_with_history(options[selection], true);
|
|
}
|
|
if (key_pressed(KEY_RETURN)) {
|
|
play_menu_select_sound();
|
|
if (selection == 0) {
|
|
adopt_pet(soundPath);
|
|
return true;
|
|
}
|
|
speak_with_history("Declined.", true);
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void attempt_pet_offer_random(const string&in reasonText) {
|
|
if (petActive) return;
|
|
if (!has_pet_food_available()) return;
|
|
init_pet_sounds();
|
|
if (petSoundPaths.length() == 0) return;
|
|
int pick = random(0, petSoundPaths.length() - 1);
|
|
run_pet_offer_menu(petSoundPaths[pick], reasonText);
|
|
}
|
|
|
|
void attempt_pet_offer_from_quest(int score) {
|
|
if (score < QUEST_LOG_SCORE) return;
|
|
attempt_pet_offer_random("");
|
|
}
|
|
|
|
void attempt_pet_offer_from_adventure() {
|
|
if (petActive) return;
|
|
if (random(1, 100) > PET_ADVENTURE_CHANCE) return;
|
|
attempt_pet_offer_random("");
|
|
}
|
|
|
|
void attempt_pet_offer_from_tree() {
|
|
if (petActive) return;
|
|
if (random(1, 100) > PET_TREE_HAWK_CHANCE) return;
|
|
string hawkSound = get_pet_sound_for_name("hawk");
|
|
if (hawkSound == "") return;
|
|
run_pet_offer_menu(hawkSound, "");
|
|
}
|
|
|
|
bool try_pet_pickup_small_game(const string&in gameType, string &out message) {
|
|
if (get_personal_count(ITEM_SMALL_GAME) >= get_personal_stack_limit()) {
|
|
return false;
|
|
}
|
|
add_personal_count(ITEM_SMALL_GAME, 1);
|
|
personal_small_game_types.insert_last(gameType);
|
|
message = "Your " + petType + " retrieved " + gameType + ".";
|
|
return true;
|
|
}
|
|
|
|
bool try_pet_pickup_world_drop(WorldDrop@ drop, string &out message) {
|
|
if (drop is null) return false;
|
|
if (get_flying_creature_config_by_drop_type(drop.type) !is null) {
|
|
return try_pet_pickup_small_game(drop.type, message);
|
|
}
|
|
if (drop.type == "arrow") {
|
|
int maxArrows = get_arrow_limit();
|
|
if (maxArrows <= 0) {
|
|
return false;
|
|
}
|
|
if (get_personal_count(ITEM_ARROWS) >= maxArrows) {
|
|
return false;
|
|
}
|
|
add_personal_count(ITEM_ARROWS, 1);
|
|
message = "Your " + petType + " retrieved an arrow.";
|
|
return true;
|
|
}
|
|
if (drop.type == "boar carcass") {
|
|
if (get_personal_count(ITEM_BOAR_CARCASSES) >= get_personal_stack_limit()) {
|
|
return false;
|
|
}
|
|
add_personal_count(ITEM_BOAR_CARCASSES, 1);
|
|
message = "Your " + petType + " retrieved a boar carcass.";
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
WorldDrop@ find_pet_drop_target() {
|
|
int bestDistance = PET_RANGE + 1;
|
|
WorldDrop@ best = null;
|
|
for (uint i = 0; i < world_drops.length(); i++) {
|
|
int distance = abs(world_drops[i].position - x);
|
|
if (distance > PET_RANGE) continue;
|
|
if (distance < bestDistance) {
|
|
bestDistance = distance;
|
|
@best = world_drops[i];
|
|
}
|
|
}
|
|
return best;
|
|
}
|
|
|
|
void update_pet_retrieval() {
|
|
if (!petActive) return;
|
|
if (!petOut) return;
|
|
if (petLoyalty <= 0) return;
|
|
if (petRetrieveTimer.elapsed < PET_RETRIEVE_COOLDOWN) return;
|
|
if (petEventMessages.length() > 2) return;
|
|
if (petTravelActive) return;
|
|
|
|
WorldDrop@ drop = find_pet_drop_target();
|
|
if (drop is null) return;
|
|
|
|
petRetrieveTimer.restart();
|
|
start_pet_travel_retrieve(drop.position);
|
|
}
|
|
|
|
bool find_pet_attack_target(int &out targetPos, string &out targetLabel, int &out targetKind) {
|
|
int bestDistance = PET_RANGE + 1;
|
|
targetPos = -1;
|
|
targetLabel = "";
|
|
targetKind = -1;
|
|
|
|
for (uint i = 0; i < bandits.length(); i++) {
|
|
int distance = abs(bandits[i].position - x);
|
|
if (distance > PET_RANGE) continue;
|
|
if (distance < bestDistance) {
|
|
bestDistance = distance;
|
|
targetPos = bandits[i].position;
|
|
targetLabel = "bandit";
|
|
targetKind = 0;
|
|
}
|
|
}
|
|
|
|
for (uint i = 0; i < undeads.length(); i++) {
|
|
if (undeads[i].undead_type == "undead_resident") continue;
|
|
int distance = abs(undeads[i].position - x);
|
|
if (distance > PET_RANGE) continue;
|
|
if (distance < bestDistance) {
|
|
bestDistance = distance;
|
|
targetPos = undeads[i].position;
|
|
targetLabel = "undead";
|
|
targetKind = 1;
|
|
}
|
|
}
|
|
|
|
for (uint i = 0; i < ground_games.length(); i++) {
|
|
int distance = abs(ground_games[i].position - x);
|
|
if (distance > PET_RANGE) continue;
|
|
if (distance < bestDistance) {
|
|
bestDistance = distance;
|
|
targetPos = ground_games[i].position;
|
|
targetLabel = "boar";
|
|
targetKind = 2;
|
|
}
|
|
}
|
|
|
|
return targetPos != -1;
|
|
}
|
|
|
|
void update_pet_attack() {
|
|
if (!petActive) return;
|
|
if (!petOut) return;
|
|
if (petLoyalty <= 0) return;
|
|
if (petAttackTimer.elapsed < PET_ATTACK_COOLDOWN) return;
|
|
if (petTravelActive) return;
|
|
|
|
int targetPos = -1;
|
|
string targetLabel = "";
|
|
int targetKind = -1;
|
|
if (!find_pet_attack_target(targetPos, targetLabel, targetKind)) return;
|
|
|
|
petAttackTimer.restart();
|
|
start_pet_travel_attack(targetPos, targetLabel, targetKind);
|
|
}
|
|
|
|
void attempt_pet_random_find() {
|
|
if (!petActive) return;
|
|
if (!petOut) return;
|
|
if (petLoyalty < PET_LOYALTY_BONUS_THRESHOLD) return;
|
|
if (random(1, 100) > PET_RANDOM_FIND_CHANCE) return;
|
|
|
|
int[] possibleItems = {ITEM_STICKS, ITEM_VINES, ITEM_STONES, ITEM_CLAY};
|
|
int itemType = possibleItems[random(0, possibleItems.length() - 1)];
|
|
int added = add_to_stack(get_personal_count(itemType), 1);
|
|
if (added <= 0) return;
|
|
|
|
add_personal_count(itemType, added);
|
|
string itemName = (added == 1) ? item_registry[itemType].singular : item_registry[itemType].name;
|
|
queue_pet_event("Your " + petType + " retrieved " + added + " " + itemName + ".", x);
|
|
adjust_pet_loyalty(-PET_LOYALTY_ACTION_COST);
|
|
petOut = false;
|
|
}
|
|
|
|
void handle_pet_hourly_update(int hour) {
|
|
if (!petActive) return;
|
|
|
|
if (get_pet_food_personal_total() == 0) {
|
|
adjust_pet_loyalty(-PET_LOYALTY_HUNGER_LOSS);
|
|
}
|
|
|
|
if (!petActive) return;
|
|
|
|
if (hour % 8 == 0) {
|
|
if (consume_pet_food()) {
|
|
petLoyalty += PET_LOYALTY_EAT_BONUS;
|
|
clamp_pet_loyalty();
|
|
}
|
|
}
|
|
|
|
attempt_pet_random_find();
|
|
}
|
|
|
|
void update_pets() {
|
|
update_pet_travel();
|
|
if (petActive && petOut) {
|
|
update_pet_retrieval();
|
|
update_pet_attack();
|
|
}
|
|
update_pet_events();
|
|
}
|