short good_attack_room(struct Thing *thing) { // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero %s index %d owner %d - reset",thing_model_name(thing),(int)thing->index,(int)thing->owner); set_start_state(thing); return 0; } //return _DK_good_attack_room(thing); MapSlabCoord base_slb_x,base_slb_y; base_slb_x = subtile_slab_fast(thing->mappos.x.stl.num); base_slb_y = subtile_slab_fast(thing->mappos.y.stl.num); struct Room *room; room = slab_room_get(base_slb_x, base_slb_y); // If the current tile can be destroyed if (room_exists(room) && (room->owner != thing->owner) && !room_cannot_vandalise(room->kind)) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (cctrl->instance_id == CrInst_NULL) { set_creature_instance(thing, CrInst_ATTACK_ROOM_SLAB, 1, 0, 0); MapCoord ev_coord_x,ev_coord_y; ev_coord_x = subtile_coord_center(room->central_stl_x); ev_coord_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ev_coord_x, ev_coord_y, EvKind_RoomUnderAttack, room->owner, 0); if (is_my_player_number(room->owner)) output_message(SMsg_EnemyDestroyRooms, MESSAGE_DELAY_FIGHT, true); } return 1; } // Otherwise, search around for a tile to destroy long m,n; m = ACTION_RANDOM(SMALL_AROUND_SLAB_LENGTH); for (n=0; n < SMALL_AROUND_SLAB_LENGTH; n++) { MapSlabCoord slb_x,slb_y; slb_x = base_slb_x + (long)small_around[m].delta_x; slb_y = base_slb_y + (long)small_around[m].delta_y; room = slab_room_get(slb_x, slb_y); if (room_exists(room) && (room->owner != thing->owner)) { if (setup_person_move_to_position(thing, slb_x, slb_y, NavRtF_Default)) { thing->continue_state = CrSt_GoodAttackRoom1; return 1; } } m = (m+1) % SMALL_AROUND_SLAB_LENGTH; } set_start_state(thing); return 0; }
TbBool attempt_job_move_to_event_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job) { EventKind evkind; struct Event *event; evkind = get_event_for_job(new_job); event = get_event_of_type_for_player(evkind, creatng->owner); // Treat heart attack as enemy fight, too if (event_is_invalid(event) && (evkind == EvKind_EnemyFight)) { event = get_event_of_type_for_player(EvKind_HeartAttacked, creatng->owner); } if (event_is_invalid(event)) { return false; } if (!setup_person_move_to_position(creatng, coord_subtile(event->mappos_x), coord_subtile(event->mappos_y), NavRtF_Default)) { return false; } creatng->continue_state = get_initial_state_for_job(new_job); return true; }
TbBool setup_head_for_random_unused_lair_slab(struct Thing *creatng, struct Room *room) { SlabCodedCoords slbnum; long n; unsigned long k; n = ACTION_RANDOM(room->slabs_count); slbnum = room->slabs_list; for (k = n; k > 0; k--) { if (slbnum == 0) break; slbnum = get_next_slab_number_in_room(slbnum); } if (slbnum == 0) { ERRORLOG("Taking random slab (%d/%d) in %s index %d failed - internal inconsistency.",(int)n,(int)room->slabs_count,room_code_name(room->kind),(int)room->index); slbnum = room->slabs_list; } k = 0; while (1) { MapSlabCoord slb_x,slb_y; slb_x = slb_num_decode_x(slbnum); slb_y = slb_num_decode_y(slbnum); struct Thing *lairtng; lairtng = find_creature_lair_at_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 0); if (thing_is_invalid(lairtng)) { if (setup_person_move_to_position(creatng, slab_subtile_center(slb_x), slab_subtile_center(slb_y), NavRtF_Default)) { return true; } WARNLOG("Cannot get somewhere in room"); } slbnum = get_next_slab_number_in_room(slbnum); if (slbnum == 0) { slbnum = room->slabs_list; } k++; if (k >= room->slabs_count) { break; } } return false; }
short good_back_at_start(struct Thing *thing) { // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner); set_start_state(thing); return false; } //return _DK_good_back_at_start(thing); if (thing->creature.gold_carried <= 0) { set_start_state(thing); return 1; } SubtlCodedCoords stl_num; long m,n; stl_num = get_subtile_number(thing->mappos.x.stl.num,thing->mappos.y.stl.num); m = ACTION_RANDOM(AROUND_MAP_LENGTH); for (n=0; n < AROUND_MAP_LENGTH; n++) { struct Map *mapblk; mapblk = get_map_block_at_pos(stl_num+around_map[m]); // Per-block code if ((mapblk->flags & MapFlg_IsTall) == 0) { MapSubtlCoord stl_x, stl_y; stl_x = stl_num_decode_x(stl_num+around_map[m]); stl_y = stl_num_decode_y(stl_num+around_map[m]); if (setup_person_move_to_position(thing, stl_x, stl_y, NavRtF_Default)) { thing->continue_state = CrSt_GoodDropsGold; return 1; } } // Per-block code ends m = (m + 1) % AROUND_MAP_LENGTH; } set_start_state(thing); return 1; }
TbBool attempt_job_work_in_room_and_cure_near_pos(struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, CreatureJob new_job) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); SYNCDBG(16,"Starting for %s (owner %d) and job %s",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job)); struct Room *room; room = subtile_room_get(stl_x, stl_y); 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; } struct Coord3d pos; if (!find_first_valid_position_for_thing_in_room(creatng, room, &pos)) { return false; } if (!setup_person_move_to_position(creatng, pos.x.stl.num, pos.y.stl.num, NavRtF_Default)) { return false; } creatng->continue_state = get_arrive_at_state_for_job(new_job); cctrl->target_room_id = room->index; process_temple_cure(creatng); return true; }