struct Room * find_nearest_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, PlayerNumber owner, RoomKind rkind, unsigned char nav_flags, long used, long *neardistance) { struct Dungeon *dungeon; struct Room *nearoom; long distance; int i; SYNCDBG(18,"Searching for %s navigable by %s index %d",room_code_name(rkind),thing_model_name(thing),(int)thing->index); dungeon = get_dungeon(owner); nearoom = INVALID_ROOM; distance = *neardistance; i = dungeon->room_kind[rkind]; while (i != 0) { struct Room *room; room = find_next_navigable_room_for_thing_with_capacity_and_closer_than(thing, i, nav_flags, used, &distance); if (room_is_invalid(room)) { break; } // Found closer room i = room->next_of_owner; nearoom = room; } *neardistance = distance; return nearoom; }
long instf_attack_room_slab(struct Thing *creatng, long *param) { TRACE_THING(creatng); //return _DK_instf_attack_room_slab(creatng, param); struct Room *room; room = get_room_thing_is_on(creatng); if (room_is_invalid(room)) { ERRORLOG("The %s is not on room",thing_model_name(creatng)); return 0; } struct SlabMap *slb; slb = get_slabmap_thing_is_on(creatng); if (slb->health > 2) { //TODO CONFIG damage made to room slabs is constant - doesn't look good slb->health -= 2; thing_play_sample(creatng, 128 + UNSYNC_RANDOM(3), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return 1; } if (room->owner != game.neutral_player_num) { struct Dungeon *dungeon; dungeon = get_dungeon(room->owner); dungeon->rooms_destroyed++; } if (!delete_room_slab(coord_slab(creatng->mappos.x.val), coord_slab(creatng->mappos.y.val), 1)) { ERRORLOG("Cannot delete %s room tile destroyed by %s",room_code_name(room->kind),thing_model_name(creatng)); return 0; } create_effect(&creatng->mappos, 3, creatng->owner); thing_play_sample(creatng, 47, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return 1; }
struct Room *get_hated_room_for_quick_attack(struct Computer2 *comp, long min_hate) { struct THate hates[PLAYERS_COUNT]; long i; SYNCDBG(8,"Starting for player %d",(int)comp->dungeon->owner); get_opponent(comp, hates); // note that 'i' is not player index, player index is inside THate struct for (i=0; i < PLAYERS_COUNT; i++) { struct THate *hate; hate = &hates[i]; if (players_are_enemies(comp->dungeon->owner, hate->plyr_idx)) { if ((hate->pos_near != NULL) && (hate->amount > min_hate)) { struct Room *room; room = get_opponent_room(comp, hate->plyr_idx); if (!room_is_invalid(room)) { return room; } } } } return INVALID_ROOM; }
long count_player_rooms_entrances(PlayerNumber plyr_idx) { struct Room *room; long i; unsigned long k; long count; count = 0; i = game.entrance_room_id; k = 0; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_kind; // Per-room code if ((plyr_idx < 0) || (room->owner == plyr_idx)) count++; // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return count; }
long process_lair_enemy(struct Thing *thing, struct Room *room) { struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Thing *enemytng; long combat_factor; cctrl = creature_control_get_from_thing(thing); // Shouldn't be possible. But just for sure. if (room_is_invalid(room)) { return 0; } // If the room changed during creature's journey, end if ((room->kind != RoK_LAIR) || (room->owner != thing->owner) || (room->index != cctrl->lair_room_id)) { return 0; } crstat = creature_stats_get_from_thing(thing); // End if the creature has no lair enemy if (crstat->lair_enemy == 0) { return 0; } // Search for enemies no often than every 64 turns if (((game.play_gameturn + thing->index) & 0x3F) != 0) { return 0; } combat_factor = find_fellow_creature_to_fight_in_room(thing,room,crstat->lair_enemy,&enemytng); if (combat_factor < 1) return 0; if (!set_creature_in_combat_to_the_death(thing, enemytng, combat_factor)) return 0; return 1; }
TbBool good_setup_attack_rooms(struct Thing *creatng, long dngn_id) { struct Room *room; struct CreatureControl *cctrl; struct Coord3d pos; room = find_nearest_room_for_thing_excluding_two_types(creatng, dngn_id, 7, 1, 1); if (room_is_invalid(room)) { return false; } if (!find_random_valid_position_for_thing_in_room(creatng, room, &pos) || !creature_can_navigate_to_with_storage(creatng, &pos, NavRtF_NoOwner) ) { ERRORLOG("The %s cannot destroy %s because it can't reach position within it",thing_model_name(creatng),room_code_name(room->kind)); return false; } if (!setup_random_head_for_room(creatng, room, NavRtF_NoOwner)) { ERRORLOG("The %s cannot destroy %s because it can't head for it",thing_model_name(creatng),room_code_name(room->kind)); return false; } cctrl = creature_control_get_from_thing(creatng); creatng->continue_state = CrSt_GoodArrivedAtAttackRoom; cctrl->target_room_id = room->index; return true; }
TbBool good_setup_loot_research_room(struct Thing *thing, long dngn_id) { struct CreatureControl *cctrl; struct Room *room; room = find_random_room_creature_can_navigate_to(thing, dngn_id, RoK_LIBRARY, NavRtF_Default); if (room_is_invalid(room)) { SYNCDBG(6,"No accessible player %d library found",(int)dngn_id); return false; } struct Coord3d pos; if (!find_random_valid_position_for_thing_in_room(thing, room, &pos)) { SYNCDBG(6,"No position for %s index %d in %s owned by player %d", thing_model_name(thing),(int)thing->index,room_code_name(room->kind),(int)room->owner); return false; } if (!setup_person_move_to_coord(thing, &pos, NavRtF_Default)) { SYNCDBG(6,"Cannot setup move %s index %d to %s owned by player %d", thing_model_name(thing),(int)thing->index,room_code_name(room->kind),(int)room->owner); return false; } cctrl = creature_control_get_from_thing(thing); thing->continue_state = CrSt_CreatureSearchForSpellToStealInRoom; cctrl->target_room_id = room->index; return true; }
TbBool creature_can_freeze_prisoners_for_player(const struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job) { // To freeze prisoners, our prison can't be empty struct Room *room; room = find_room_for_thing_with_used_capacity(creatng, creatng->owner, get_room_for_job(Job_FREEZE_PRISONERS), NavRtF_Default, 1); return creature_instance_is_available(creatng, CrInst_FREEZE) && !room_is_invalid(room); }
TbBool attempt_job_work_in_room_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job) { struct Coord3d pos; struct Room *room; RoomKind rkind; rkind = get_room_for_job(new_job); SYNCDBG(6,"Starting for %s (owner %d) and job %s in %s room",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job),room_code_name(rkind)); if ((get_flags_for_job(new_job) & JoKF_NeedsCapacity) != 0) { room = find_nearest_room_for_thing_with_spare_capacity(creatng, creatng->owner, rkind, NavRtF_Default, 1); } else { room = find_nearest_room_for_thing(creatng, creatng->owner, rkind, NavRtF_Default); } if (room_is_invalid(room)) { return false; } if (!find_random_valid_position_for_thing_in_room(creatng, room, &pos)) { return false; } if (get_arrive_at_state_for_job(new_job) == CrSt_Unused) { ERRORLOG("No arrive at state for job %s in %s room",creature_job_code_name(new_job),room_code_name(room->kind)); return false; } if (!setup_person_move_to_coord(creatng, &pos, NavRtF_Default)) { return false; } struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); creatng->continue_state = get_arrive_at_state_for_job(new_job); cctrl->target_room_id = room->index; return true; }
TbBool attempt_anger_job_destroy_rooms(struct Thing *creatng) { //return _DK_attempt_anger_job_destroy_rooms(creatng); if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreatureVandaliseRooms)) { return false; } struct Room *room; struct Coord3d pos; room = find_nearest_room_for_thing_excluding_two_types(creatng, creatng->owner, 7, 1, 1); if (room_is_invalid(room)) { return false; } if (!find_random_valid_position_for_thing_in_room(creatng, room, &pos)) { return false; } if (!creature_can_navigate_to_with_storage(creatng, &pos, NavRtF_NoOwner)) { return false; } if (!external_set_thing_state(creatng, CrSt_CreatureVandaliseRooms)) { return false; } if (!setup_random_head_for_room(creatng, room, NavRtF_NoOwner)) { return false; } struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); creatng->continue_state = CrSt_CreatureVandaliseRooms; cctrl->target_room_id = room->index; return true; }
long computer_check_for_place_door(struct Computer2 *comp, struct ComputerCheck * check) { if (is_newdig_enabled(comp)) return 4; SYNCDBG(8,"Starting"); ThingModel doorkind; struct Dungeon *dungeon; dungeon = comp->dungeon; //TODO COMPUTER_PLAYER Computer prefers to put wooden doors, and uses other types only if wooden are depleted. That should be changed. for (doorkind = 1; doorkind < DOOR_TYPES_COUNT; doorkind++) { if (dungeon->door_amount_stored[doorkind] <= 0) { continue; } long rkind; rkind = check->param1; if (rkind == 0) { rkind = (check->param2 + 1) % ROOM_TYPES_COUNT; check->param2 = rkind; } unsigned long k; k = 0; long i; i = dungeon->room_kind[rkind]; while (i != 0) { struct Room *room; room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code struct Coord3d pos; pos.x.val = 0; pos.y.val = 0; pos.z.val = 0; if (find_place_to_put_door_around_room(room, &pos)) { if (try_game_action(comp, dungeon->owner, GA_PlaceDoor, 0, pos.x.stl.num, pos.y.stl.num, doorkind, 0) > Lb_OK) { return CTaskRet_Unk1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } } return CTaskRet_Unk4; }
short creature_sleep(struct Thing *thing) { //return _DK_creature_sleep(thing); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if ((cctrl->slap_turns > 0) || !creature_will_sleep(thing)) { set_start_state(thing); return 0; } struct Room *room; room = get_room_thing_is_on(thing); if (room_is_invalid(room) || (room->kind != RoK_LAIR) || (cctrl->lair_room_id != room->index) || (room->owner != thing->owner)) { set_start_state(thing); return 0; } thing->movement_flags &= ~0x0020; struct CreatureStats *crstat; crstat = creature_stats_get_from_thing(thing); if (((game.play_gameturn + thing->index) % game.recovery_frequency) == 0) { HitPoints recover; recover = compute_creature_max_health(crstat->sleep_recovery, cctrl->explevel); apply_health_to_thing_and_display_health(thing, recover); } anger_set_creature_anger(thing, 0, AngR_NoLair); anger_apply_anger_to_creature(thing, crstat->annoy_sleeping, AngR_Other, 1); if (cctrl->field_82 > 0) { cctrl->field_82--; } if (((game.play_gameturn + thing->index) & 0x3F) == 0) { if (ACTION_RANDOM(100) < 5) { struct Dungeon *dungeon; dungeon = get_dungeon(thing->owner); dungeon->lvstats.backs_stabbed++; } } if (crstat->sleep_exp_slab != SlbT_ROCK) { if (creature_can_gain_experience(thing) && room_has_slab_adjacent(room, crstat->sleep_exp_slab)) { cctrl->exp_points += crstat->sleep_experience; check_experience_upgrade(thing); } } { HitPoints health_max; health_max = compute_creature_max_health(crstat->health, cctrl->explevel); if ((crstat->heal_threshold * health_max / 256 <= thing->health) && (!cctrl->field_82)) { set_start_state(thing); return 1; } } process_lair_enemy(thing, room); return 0; }
long instf_destroy(struct Thing *creatng, long *param) { struct Dungeon *dungeon; struct Room *room; struct SlabMap *slb; MapSlabCoord slb_x,slb_y; long prev_owner; TRACE_THING(creatng); slb_x = subtile_slab_fast(creatng->mappos.x.stl.num); slb_y = subtile_slab_fast(creatng->mappos.y.stl.num); dungeon = get_dungeon(creatng->owner); slb = get_slabmap_block(slb_x, slb_y); room = room_get(slb->room_index); prev_owner = slabmap_owner(slb); if ( !room_is_invalid(room) && (prev_owner != creatng->owner) ) { if (room->health > 1) { room->health--; return 0; } clear_dig_on_room_slabs(room, creatng->owner); if (room->owner == game.neutral_player_num) { claim_room(room, creatng); } else { MapCoord ccor_x,ccor_y; ccor_x = subtile_coord_center(room->central_stl_x); ccor_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ccor_x, ccor_y, EvKind_RoomLost, room->owner, 0); claim_enemy_room(room, creatng); } thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); create_effects_on_room_slabs(room, imp_spangle_effects[creatng->owner], 0, creatng->owner); return 0; } if (slb->health > 1) { slb->health--; return 0; } if (prev_owner != game.neutral_player_num) { struct Dungeon *prev_dungeon; prev_dungeon = get_dungeon(prev_owner); prev_dungeon->lvstats.territory_lost++; } decrease_dungeon_area(prev_owner, 1); neutralise_enemy_block(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng->owner); remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL); switch_owned_objects_on_destoyed_slab_to_neutral(slb_x, slb_y, prev_owner); dungeon->lvstats.territory_destroyed++; return 1; }
struct Room * find_next_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, int prev_room_idx, unsigned char nav_flags, long used, long *neardistance) { long distance; struct Coord3d pos; struct Room *room; unsigned long k; int i; k = 0; i = prev_room_idx; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code // Compute simplified distance - without use of mul or div distance = abs(thing->mappos.x.stl.num - (int)room->central_stl_x) + abs(thing->mappos.y.stl.num - (int)room->central_stl_y); if ((*neardistance > distance) && (room->used_capacity >= used)) { if (find_first_valid_position_for_thing_anywhere_in_room(thing, room, &pos)) { TbBool is_connected; switch (thing->class_id) { case TCls_Creature: is_connected = creature_can_navigate_to(thing, &pos, nav_flags); break; default: is_connected = navigation_points_connected(&thing->mappos, &pos); break; } if (is_connected) { *neardistance = distance; return room; } } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return INVALID_ROOM; }
long computer_check_neutral_places(struct Computer2 *comp, struct ComputerCheck * check) { SYNCDBG(8,"Starting"); //return _DK_computer_check_neutral_places(comp, check); struct Comp2_UnkStr1 *rel; rel = &comp->unkarr_A10[game.neutral_player_num]; struct Room *near_room; struct Coord3d *near_pos; int near_dist; near_room = INVALID_ROOM; near_dist = 2147483647; near_pos = &rel->pos_A[0]; int i; for (i=0; i < 64; i++) { struct Coord3d *place; place = &rel->pos_A[i]; if ((place->x.val == 0) || (place->y.val == 0)) { continue; } struct Room *room; room = INVALID_ROOM; if (computer_finds_nearest_room_to_pos(comp, &room, place)) { MapSubtlDelta dx,dy; dx = abs((int)room->central_stl_x - (MapSubtlDelta)place->x.stl.num); dy = abs((int)room->central_stl_y - (MapSubtlDelta)place->y.stl.num); if (near_dist > dx+dy) { near_room = room; near_pos = place; near_dist = dx+dy; } } } if (room_is_invalid(near_room)) { return 4; } struct Coord3d endpos; struct Coord3d startpos; endpos.x.val = near_pos->x.val; endpos.y.val = near_pos->y.val; endpos.z.val = near_pos->z.val; startpos.x.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_x)); startpos.y.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_y)); startpos.z.val = subtile_coord(1,0); if (!create_task_dig_to_neutral(comp, startpos, endpos)) { return 4; } near_pos->x.val = 0; near_pos->y.val = 0; near_pos->z.val = 0; return 1; }
TbBool attempt_job_in_state_on_room_content_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job) { struct Room *room; RoomKind rkind; rkind = get_room_for_job(new_job); room = find_room_for_thing_with_used_capacity(creatng, creatng->owner, rkind, NavRtF_Default, 1); if (room_is_invalid(room)) { return false; } internal_set_thing_state(creatng, get_initial_state_for_job(new_job)); return true; }
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; struct Room *room; dungeon = comp->dungeon; SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2)); int num_to_move; num_to_move = check->param1 * dungeon->num_active_creatrs / 100; if (num_to_move <= 0) { SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1); return CTaskRet_Unk4; } if (computer_able_to_use_magic(comp, PwrK_HAND, 1, num_to_move) != 1) { return CTaskRet_Unk4; } // If there's already task in progress which uses hand, then don't add more // content of the hand could be used by wrong task by mistake if (is_task_in_progress_using_hand(comp)) { return CTaskRet_Unk4; } unsigned long k; long i; k = 0; i = dungeon->room_kind[check->param2]; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code if (room->total_capacity > room->used_capacity) { int num_to_move_fit; num_to_move_fit = min(num_to_move, room->total_capacity - room->used_capacity); if (create_task_move_creatures_to_room(comp, room->index, num_to_move_fit)) { SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move_fit,room_code_name(room->kind),(int)room->index); return CTaskRet_Unk1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return CTaskRet_Unk4; }
void init_dungeon_essential_position(struct Dungeon *dungeon) { struct Room *room; room = room_get(dungeon->room_kind[RoK_DUNGHEART]); RoomKind rkind; for (rkind = 1; rkind < ROOM_TYPES_COUNT; rkind++) { if (!room_is_invalid(room)) break; room = room_get(dungeon->room_kind[rkind]); } if (room_is_invalid(room)) { dungeon->essential_pos.x.val = subtile_coord_center(map_subtiles_x/2); dungeon->essential_pos.y.val = subtile_coord_center(map_subtiles_y/2); dungeon->essential_pos.z.val = subtile_coord(0,1); return; } dungeon->essential_pos.x.val = subtile_coord_center(room->central_stl_x); dungeon->essential_pos.y.val = subtile_coord_center(room->central_stl_y); dungeon->essential_pos.z.val = subtile_coord(0,1); }
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; struct Room *room; dungeon = comp->dungeon; SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2)); //return _DK_computer_check_move_creatures_to_room(comp, check); //TODO check if should be changed to computer_able_to_use_magic() if (!is_power_available(dungeon->owner, PwrK_HAND)) { return 4; } int num_to_move; num_to_move = check->param1 * dungeon->num_active_creatrs / 100; if (num_to_move <= 0) { SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1); return 4; } if (is_task_in_progress(comp, CTT_MoveCreatureToRoom)) { return 4; } unsigned long k; long i; k = 0; i = dungeon->room_kind[check->param2]; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code if (room->total_capacity > room->used_capacity) { if (create_task_move_creatures_to_room(comp, room->index, num_to_move)) { SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move,room_code_name(room->kind),(int)room->index); return 1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return 4; }
struct Room * find_nearest_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, PlayerNumber owner, RoomKind rkind, unsigned char nav_flags, long used, long *neardistance) { struct Dungeon *dungeon; struct Room *nearoom; long distance; struct Coord3d pos; struct Room *room; unsigned long k; int i; SYNCDBG(18,"Searching for %s navigable by %s index %d",room_code_name(rkind),thing_model_name(thing),(int)thing->index); dungeon = get_dungeon(owner); nearoom = INVALID_ROOM; k = 0; i = dungeon->room_kind[rkind]; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code // Compute simplified distance - without use of mul or div distance = abs(thing->mappos.x.stl.num - (int)room->central_stl_x) + abs(thing->mappos.y.stl.num - (int)room->central_stl_y); if ((*neardistance > distance) && (room->used_capacity >= used)) { if (find_first_valid_position_for_thing_anywhere_in_room(thing, room, &pos)) { if ((thing->class_id != TCls_Creature) || creature_can_navigate_to(thing, &pos, nav_flags)) { *neardistance = distance; nearoom = room; } } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return nearoom; }
short creature_scavenged_disappear(struct Thing *thing) { struct CreatureControl *cctrl; struct Dungeon *dungeon; struct Room *room; struct Coord3d pos; long stl_x, stl_y; long i; //return _DK_creature_scavenged_disappear(thing); cctrl = creature_control_get_from_thing(thing); cctrl->byte_9A--; if (cctrl->byte_9A > 0) { if ((cctrl->byte_9A == 7) && (cctrl->byte_9B < PLAYERS_COUNT)) { create_effect(&thing->mappos, get_scavenge_effect_element(cctrl->byte_9B), thing->owner); } return 0; } // We don't really have to convert coordinates into numbers and back to XY. i = get_subtile_number(cctrl->scavenge.stl_9D_x, cctrl->scavenge.stl_9D_y); stl_x = stl_num_decode_x(i); stl_y = stl_num_decode_y(i); room = subtile_room_get(stl_x, stl_y); if (room_is_invalid(room) || (room->kind != RoK_SCAVENGER)) { ERRORLOG("Room %s at (%d,%d) disappeared.",room_code_name(RoK_SCAVENGER),(int)stl_x,(int)stl_y); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); return -1; } if (find_random_valid_position_for_thing_in_room(thing, room, &pos)) { move_thing_in_map(thing, &pos); anger_set_creature_anger_all_types(thing, 0); dungeon = get_dungeon(cctrl->byte_9B); dungeon->creatures_scavenge_gain++; if (is_my_player_number(thing->owner)) output_message(SMsg_MinionScanvenged, 0, true); cctrl->byte_9C = thing->owner; change_creature_owner(thing, cctrl->byte_9B); internal_set_thing_state(thing, CrSt_CreatureScavengedReappear); return 0; } else { ERRORLOG("No valid position inside %s room for %s.",room_code_name(room->kind),thing_model_name(thing)); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); return -1; } }
void find_nearest_rooms_for_ambient_sound(void) { struct PlayerInfo *player; struct Room *room; struct MapOffset *sstep; struct Coord3d pos; long slb_x,slb_y; MapSubtlCoord stl_x,stl_y; long i,k; SYNCDBG(8,"Starting"); if ((SoundDisabled) || (GetCurrentSoundMasterVolume() <= 0)) return; player = get_my_player(); struct Camera *cam; cam = player->acamera; if (cam == NULL) { ERRORLOG("No active camera"); set_room_playing_ambient_sound(NULL, 0); return; } slb_x = subtile_slab(cam->mappos.x.stl.num); slb_y = subtile_slab(cam->mappos.y.stl.num); for (i = 0; i < 11*11; i++) { sstep = &spiral_step[i]; stl_x = slab_subtile_center(slb_x + sstep->h); stl_y = slab_subtile_center(slb_y + sstep->v); if (subtile_is_player_room(player->id_number,stl_x,stl_y)) { room = subtile_room_get(stl_x, stl_y); if (room_is_invalid(room)) continue; struct RoomConfigStats *roomst; roomst = &slab_conf.room_cfgstats[room->kind]; k = roomst->ambient_snd_smp_id; if (k > 0) { SYNCDBG(8,"Playing ambient for %s at (%d,%d)",room_code_name(room->kind),(int)stl_x,(int)stl_y); pos.x.val = subtile_coord_center(stl_x); pos.y.val = subtile_coord_center(stl_y); pos.z.val = subtile_coord(1,0); set_room_playing_ambient_sound(&pos, k); return; } } } set_room_playing_ambient_sound(NULL, 0); }
long computer_check_for_expand_room_kind(struct Computer2 *comp, struct ComputerCheck * check, RoomKind rkind, long max_slabs, long around_start) { struct Dungeon *dungeon; dungeon = comp->dungeon; { struct RoomStats *rstat; rstat = room_stats_get_for_kind(rkind); // If we don't have money for the room - don't even try // Check price for two slabs - after all, we don't want to end up having nothing if (2*rstat->cost >= dungeon->total_money_owned) { return 0; } } MapSubtlCoord max_radius; // Don't allow the room to be made into long, narrow shape max_radius = 3 * slab_subtile(LbSqrL(max_slabs),2) / 4; struct Room *room; long i; unsigned long k; i = dungeon->room_kind[rkind]; k = 0; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code if ((room->slabs_count > 0) && (room->slabs_count < max_slabs)) { if (computer_check_for_expand_specific_room(comp, check, room, max_radius, around_start)) { SYNCDBG(6,"The %s index %d will be expanded",room_code_name(room->kind),(int)room->index); return 1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return 0; }
void find_nearest_rooms_for_ambient_sound(void) { struct PlayerInfo *player; struct Room *room; struct MapOffset *sstep; struct Coord3d pos; long slb_x,slb_y; long stl_x,stl_y; long i,k; SYNCDBG(8,"Starting"); //_DK_find_nearest_rooms_for_ambient_sound(); if ((SoundDisabled) || (GetCurrentSoundMasterVolume() <= 0)) return; player = get_my_player(); if (player->acamera == NULL) { ERRORLOG("No active camera"); set_room_playing_ambient_sound(NULL, 0); return; } slb_x = subtile_slab(player->acamera->mappos.x.stl.num); slb_y = subtile_slab(player->acamera->mappos.y.stl.num); for (i = 0; i < 120; i++) { sstep = &spiral_step[i]; stl_x = 3 * (slb_x + sstep->h); stl_y = 3 * (slb_y + sstep->v); if (subtile_is_player_room(player->id_number,stl_x,stl_y)) { room = subtile_room_get(stl_x, stl_y); if (room_is_invalid(room)) continue; k = room_info[room->kind].field_4; if (k > 0) { pos.x.val = (stl_x << 8); pos.y.val = (stl_y << 8); pos.z.val = (1 << 8); set_room_playing_ambient_sound(&pos, k); return; } } } set_room_playing_ambient_sound(NULL, 0); }
struct Room *get_player_room_of_kind_nearest_to(PlayerNumber plyr_idx, RoomKind rkind, MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *retdist) { struct Dungeon *dungeon; struct Room *room; long i; unsigned long k; dungeon = get_dungeon(plyr_idx); struct Room *nearest_room; long nearest_dist; nearest_dist = LONG_MAX; nearest_room = INVALID_ROOM; i = dungeon->room_kind[rkind]; k = 0; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code long dist; dist = abs(room->central_stl_y - stl_y) + abs(room->central_stl_x - stl_x); if (dist < nearest_dist) { nearest_dist = dist; nearest_room = room; } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } if (retdist != NULL) *retdist = nearest_dist; return nearest_room; }
struct Thing *computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(struct Computer2 *comp, RoomKind rkind) { struct Dungeon *dungeon; struct Room *room; struct Thing *thing; long i; unsigned long k; if ((rkind < 1) || (rkind > ROOM_TYPES_COUNT)) { ERRORLOG("Invalid room kind %d",(int)rkind); return INVALID_THING; } dungeon = comp->dungeon; if (dungeon_invalid(dungeon)) { ERRORLOG("Invalid computer players dungeon"); return INVALID_THING; } i = dungeon->room_kind[rkind]; k = 0; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code thing = computer_check_creatures_in_room_for_accelerate(comp, room); if (!thing_is_invalid(thing)) return thing; // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return INVALID_THING; }
TbBool attempt_anger_job_leave_dungeon(struct Thing *creatng) { if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreatureLeaves)) { return false; } struct Room *room; room = find_nearest_room_for_thing(creatng, creatng->owner, RoK_ENTRANCE, NavRtF_Default); if (room_is_invalid(room)) { return false; } if (!external_set_thing_state(creatng, CrSt_CreatureLeaves)) { return false; } if (!setup_random_head_for_room(creatng, room, NavRtF_Default)) { return false; } creatng->continue_state = CrSt_CreatureLeaves; return true; }
short creature_choose_room_for_lair_site(struct Thing *thing) { TRACE_THING(thing); //return _DK_creature_choose_room_for_lair_site(thing); struct Room *room; room = get_best_new_lair_for_creature(thing); if (room_is_invalid(room)) { update_cannot_find_room_wth_spare_capacity_event(thing->owner, thing, RoK_LAIR); set_start_state(thing); return 0; } if (!setup_head_for_random_unused_lair_slab(thing, room)) { ERRORLOG("Chosen lair is not valid, internal inconsistency."); set_start_state(thing); return 0; } thing->continue_state = CrSt_CreatureAtNewLair; return 1; }
TbBool is_correct_position_to_perform_job(const struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, CreatureJob new_job) { const struct SlabMap *slb; slb = get_slabmap_for_subtile(stl_x, stl_y); const struct Room *room; room = subtile_room_get(stl_x, stl_y); RoomKind job_rkind; job_rkind = get_room_for_job(new_job); if (job_rkind != RoK_NONE) { if (room_is_invalid(room)) { return false; } if (room->kind != job_rkind) { return false; } } if (!is_correct_owner_to_perform_job(creatng, slabmap_owner(slb), new_job)) { return false; } return true; }
struct Room *get_player_room_any_kind_nearest_to(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *retdist) { struct Room *nearest_room; long nearest_dist; nearest_dist = LONG_MAX; nearest_room = INVALID_ROOM; RoomKind rkind; for (rkind = 1; rkind < ROOM_TYPES_COUNT; rkind++) { struct Room *room; long dist; room = get_player_room_of_kind_nearest_to(plyr_idx, rkind, stl_x, stl_y, &dist); if (!room_is_invalid(room) && (dist < nearest_dist)) { nearest_dist = dist; nearest_room = room; } } if (retdist != NULL) *retdist = nearest_dist; return nearest_room; }