short creature_drop_body_in_prison(struct Thing *thing) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); struct Thing *dragtng; dragtng = thing_get(cctrl->dragtng_idx); if (!thing_exists(dragtng) || !creature_is_being_unconscious(dragtng)) { set_start_state(thing); return 0; } if (!subtile_is_room(thing->mappos.x.stl.num, thing->mappos.y.stl.num)) { set_start_state(thing); return 0; } struct Room *room; room = get_room_thing_is_on(thing); if ((room->owner != thing->owner) || (room->kind != RoK_PRISON)) { set_start_state(thing); return 0; } make_creature_conscious(dragtng); initialise_thing_state(dragtng, CrSt_CreatureArrivedAtPrison); struct CreatureControl *dragctrl; dragctrl = creature_control_get_from_thing(dragtng); dragctrl->flgfield_1 |= CCFlg_NoCompControl; set_start_state(thing); return 1; }
void process_disease(struct Thing *creatng) { SYNCDBG(18,"Starting"); //_DK_process_disease(thing); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if (!creature_affected_by_spell(creatng, SplK_Disease)) { return; } if (ACTION_RANDOM(100) < game.disease_transfer_percentage) { SubtlCodedCoords stl_num; long n; stl_num = get_subtile_number(creatng->mappos.x.stl.num,creatng->mappos.y.stl.num); for (n=0; n < AROUND_MAP_LENGTH; n++) { struct Thing *thing; struct Map *mapblk; unsigned long k; long i; mapblk = get_map_block_at_pos(stl_num+around_map[n]); k = 0; i = get_mapwho_thing_index(mapblk); while (i != 0) { thing = thing_get(i); if (thing_is_invalid(thing)) { WARNLOG("Jump out of things array"); break; } i = thing->next_on_mapblk; // Per thing code if (thing_is_creature(thing) && ((get_creature_model_flags(thing) & CMF_IsSpecDigger) == 0) && (thing->owner != cctrl->disease_caster_plyridx) && !creature_affected_by_spell(thing, SplK_Disease)) { struct CreatureControl *tngcctrl; tngcctrl = creature_control_get_from_thing(thing); apply_spell_effect_to_thing(thing, SplK_Disease, cctrl->explevel); tngcctrl->disease_caster_plyridx = cctrl->disease_caster_plyridx; } // Per thing code ends k++; if (k > THINGS_COUNT) { ERRORLOG("Infinite loop detected when sweeping things list"); erstat_inc(ESE_InfChainTngPerMapWho); break_mapwho_infinite_chain(mapblk); break; } } } } if (((game.play_gameturn - cctrl->disease_start_turn) % game.disease_lose_health_time) == 0) { apply_damage_to_thing_and_display_health(creatng, game.disease_lose_percentage_health * cctrl->max_health / 100, DmgT_Biological, cctrl->disease_caster_plyridx); } }
void increase_level(struct PlayerInfo *player) { struct Dungeon *dungeon; struct CreatureControl *cctrl; struct Thing *thing; unsigned long k; int i; dungeon = get_dungeon(player->id_number); // Increase level of normal creatures k = 0; i = dungeon->creatr_list_start; while (i != 0) { thing = thing_get(i); cctrl = creature_control_get_from_thing(thing); if (thing_is_invalid(thing) || creature_control_invalid(cctrl)) { ERRORLOG("Jump to invalid creature detected"); break; } i = cctrl->players_next_creature_idx; // Thing list loop body creature_increase_level(thing); // Thing list loop body ends k++; if (k > CREATURES_COUNT) { ERRORLOG("Infinite loop detected when sweeping creatures list"); erstat_inc(ESE_InfChainTngPerOwner); break; } } // Increase level of special workers k = 0; i = dungeon->digger_list_start; while (i != 0) { thing = thing_get(i); cctrl = creature_control_get_from_thing(thing); if (thing_is_invalid(thing) || creature_control_invalid(cctrl)) { ERRORLOG("Jump to invalid creature detected"); break; } i = cctrl->players_next_creature_idx; // Thing list loop body creature_increase_level(thing); // Thing list loop body ends k++; if (k > CREATURES_COUNT) { ERRORLOG("Infinite loop detected when sweeping creatures list"); erstat_inc(ESE_InfChainTngPerOwner); break; } } }
void setup_move_to_new_training_position(struct Thing *thing, struct Room *room, unsigned long restart) { struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Thing *prtng; struct CreatureControl *prctrl; struct Coord3d pos; long i; SYNCDBG(8,"Starting for %s",thing_model_name(thing)); //_DK_setup_move_to_new_training_position(thing, room, a3); cctrl = creature_control_get_from_thing(thing); crstat = creature_stats_get_from_thing(thing); if ( restart ) cctrl->training.search_timeout = 50; // Try partner training if ((crstat->partner_training > 0) && (ACTION_RANDOM(100) < crstat->partner_training)) { prtng = get_creature_in_training_room_which_could_accept_partner(room, thing); if (!thing_is_invalid(prtng)) { SYNCDBG(7,"The %s found %s as training partner.",thing_model_name(thing),thing_model_name(prtng)); prctrl = creature_control_get_from_thing(prtng); prctrl->training.mode = CrTrMd_PartnerTraining; prctrl->training.train_timeout = 75; prctrl->training.partner_idx = thing->index; prctrl->training.partner_creation = thing->creation_turn; cctrl->training.mode = CrTrMd_PartnerTraining; cctrl->training.train_timeout = 75; cctrl->training.partner_idx = prtng->index; cctrl->training.partner_creation = prtng->creation_turn; return; } } // No partner - train at some random position cctrl->training.mode = CrTrMd_SearchForTrainPost; if (find_random_valid_position_for_thing_in_room(thing, room, &pos)) { SYNCDBG(8,"Going to train at (%d,%d)",(int)pos.x.stl.num,(int)pos.y.stl.num); i = get_subtile_number(pos.x.stl.num,pos.y.stl.num); setup_training_move(thing, i); } else { SYNCDBG(8,"No new position found, staying at (%d,%d)",(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.x.stl.num); } if (cctrl->instance_id == CrInst_NULL) { set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0); } }
TbBool creature_move_to_using_teleport(struct Thing *thing, struct Coord3d *pos, long walk_speed) { struct CreatureControl *cctrl; short destination_valid; cctrl = creature_control_get_from_thing(thing); if (creature_instance_is_available(thing, CrInst_TELEPORT) && creature_instance_has_reset(thing, CrInst_TELEPORT) && (cctrl->instance_id == CrInst_NULL)) { // Creature can only be teleported to a revealed location destination_valid = true; if (!is_hero_thing(thing) && !is_neutral_thing(thing)) { destination_valid = subtile_revealed(pos->x.stl.num, pos->y.stl.num, thing->owner); } if (destination_valid) { // Use teleport only over large enough distances if (get_2d_box_distance(&thing->mappos, pos) > COORD_PER_STL*game.min_distance_for_teleport) { set_creature_instance(thing, CrInst_TELEPORT, 1, 0, pos); return true; } } } return false; }
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 setup_person_move_close_to_position(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y, NaviRouteFlags flags) { struct CreatureControl *cctrl; struct Coord3d trgpos; struct Coord3d navpos; SYNCDBG(18,"Moving %s index %d to (%d,%d)",thing_model_name(thing),(int)thing->index,(int)stl_x,(int)stl_y); trgpos.x.val = subtile_coord_center(stl_x); trgpos.y.val = subtile_coord_center(stl_y); trgpos.z.val = thing->mappos.z.val; cctrl = creature_control_get_from_thing(thing); if (creature_control_invalid(cctrl)) { WARNLOG("Tried to move invalid creature to (%d,%d)",(int)stl_x,(int)stl_y); return false; } get_nearest_navigable_point_for_thing(thing, &trgpos, &navpos, flags); if (!creature_can_navigate_to_with_storage(thing, &navpos, flags)) { SYNCDBG(19,"The %s cannot reach subtile (%d,%d)",thing_model_name(thing),(int)stl_x,(int)stl_y); return false; } cctrl->move_flags = flags; internal_set_thing_state(thing, CrSt_MoveToPosition); cctrl->moveto_pos.x.val = navpos.x.val; cctrl->moveto_pos.y.val = navpos.y.val; cctrl->moveto_pos.z.val = navpos.z.val; return true; }
short good_leave_through_exit_door(struct Thing *thing) { struct CreatureControl *cctrl; struct Thing *tmptng; // 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); erstat_inc(ESE_BadCreatrState); return false; } //return _DK_good_leave_through_exit_door(thing); tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num); if (thing_is_invalid(tmptng)) { return 0; } cctrl = creature_control_get_from_thing(thing); thing->creature.gold_carried = 0; cctrl->field_282 = game.hero_door_wait_time; cctrl->byte_8A = tmptng->creation_turn; place_thing_in_creature_controlled_limbo(thing); internal_set_thing_state(thing, CrSt_GoodWaitInExitDoor); return 1; }
short creature_hero_entering(struct Thing *thing) { struct CreatureControl *cctrl; TRACE_THING(thing); //return _DK_creature_hero_entering(thing); cctrl = creature_control_get_from_thing(thing); if (cctrl->field_282 > 0) { cctrl->field_282--; return CrStRet_Unchanged; } if (cctrl->field_282 == 0) { thing->mappos.z.val = get_ceiling_height(&thing->mappos) - (long)thing->field_58 - 1; cctrl->field_282--; return CrStRet_Modified; } if ( thing_touching_floor(thing) || (((thing->movement_flags & TMvF_Flying) != 0) && thing_touching_flight_altitude(thing))) { set_start_state(thing); return CrStRet_ResetOk; } if (cctrl->field_282 < -500) { set_start_state(thing); return CrStRet_ResetFail; } cctrl->field_282--; return CrStRet_Modified; }
void process_creature_instance(struct Thing *thing) { struct CreatureControl *cctrl; struct InstanceInfo *inst_inf; SYNCDBG(19,"Starting for %s index %d instance %d",thing_model_name(thing),(int)thing->index,(int)cctrl->instance_id); TRACE_THING(thing); cctrl = creature_control_get_from_thing(thing); if (cctrl->instance_id != CrInst_NULL) { cctrl->inst_turn++; if (cctrl->inst_turn == cctrl->inst_action_turns) { inst_inf = creature_instance_info_get(cctrl->instance_id); if (inst_inf->func_cb != NULL) { SYNCDBG(18,"Executing instance %d for %s index %d.",(int)cctrl->instance_id,thing_model_name(thing),(int)thing->index); inst_inf->func_cb(thing, inst_inf->func_params); } } if (cctrl->inst_turn >= cctrl->inst_total_turns) { if (cctrl->inst_repeat) { cctrl->inst_turn--; cctrl->inst_repeat = 0; return; } cctrl->instance_use_turn[cctrl->instance_id] = game.play_gameturn; cctrl->instance_id = CrInst_NULL; } cctrl->inst_repeat = 0; } }
short creature_freeze_prisonors(struct Thing *creatng) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if (cctrl->instance_id != CrInst_NULL) { return 1; } if (!creature_instance_has_reset(creatng, CrInst_FREEZE)) { if (creature_choose_random_destination_on_valid_adjacent_slab(creatng)) { creatng->continue_state = CrSt_CreatureFreezePrisoners; } return 1; } struct Thing *victng; victng = find_prisoner_for_thing(creatng); if (thing_is_invalid(victng)) { set_start_state(creatng); return 0; } long dist; dist = get_combat_distance(creatng, victng); if (dist < 156) { creature_retreat_from_combat(creatng, victng, CrSt_CreatureFreezePrisoners, 0); } else if ((dist <= 2048) && (creature_can_see_combat_path(creatng, victng, dist) > AttckT_Unset)) { set_creature_instance(creatng, CrInst_FREEZE, 1, victng->index, 0); } else { creature_move_to(creatng, &victng->mappos, cctrl->max_speed, 0, 0); } return 1; }
short at_guard_post_room(struct Thing *thing) { struct CreatureControl *cctrl; struct Room *room; cctrl = creature_control_get_from_thing(thing); cctrl->target_room_id = 0; room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, get_room_for_job(Job_GUARD), thing)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index); set_start_state(thing); return 0; } if (!add_creature_to_work_room(thing, room, Job_GUARD)) { set_start_state(thing); return 0; } internal_set_thing_state(thing, get_continue_state_for_job(Job_GUARD)); if (!person_get_somewhere_adjacent_in_room(thing, room, &cctrl->moveto_pos)) { cctrl->moveto_pos.x.val = thing->mappos.x.val; cctrl->moveto_pos.y.val = thing->mappos.y.val; cctrl->moveto_pos.z.val = thing->mappos.z.val; } return 1; }
CrCheckRet process_scavenge_function(struct Thing *calltng) { SYNCDBG(18,"Starting for %s owner %d",thing_model_name(calltng),(int)calltng->owner); //return _DK_process_scavenge_function(thing); struct CreatureControl *callctrl; callctrl = creature_control_get_from_thing(calltng); struct Dungeon *calldngn; struct Room *room; calldngn = get_dungeon(calltng->owner); room = get_room_creature_works_in(calltng); if ( !room_still_valid_as_type_for_thing(room, RoK_SCAVENGER, calltng) ) { WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(calltng),(int)calltng->owner); set_start_state(calltng); return CrCkRet_Continue; } struct CreatureStats *crstat; crstat = creature_stats_get_from_thing(calltng); if (!player_can_afford_to_scavenge_creature(calltng)) { if (is_my_player_number(calltng->owner)) output_message(SMsg_NoGoldToScavenge, 500, 1); set_start_state(calltng); return CrCkRet_Continue; } if (calldngn->scavenge_counters_turn != game.play_gameturn) { reset_scavenge_counts(calldngn); } long work_value; work_value = compute_creature_work_value(crstat->scavenge_value*256, room->efficiency, callctrl->explevel); work_value = process_work_speed_on_work_value(calltng, work_value); SYNCDBG(9,"The %s index %d owner %d produced %d scavenge points",thing_model_name(calltng),(int)calltng->index,(int)calltng->owner,(int)work_value); struct Thing *scavtng; scavtng = get_scavenger_target(calltng); if (!thing_is_invalid(scavtng)) { process_scavenge_creature_from_level(scavtng, calltng, work_value); } else if (can_scavenge_creature_from_pool(calldngn, calltng->model)) { process_scavenge_creature_from_pool(calltng, work_value); } else { if (crstat->entrance_force) { calldngn->field_1485++; } return 0; } callctrl->field_82++; if (callctrl->field_82 > game.scavenge_cost_frequency) { callctrl->field_82 -= game.scavenge_cost_frequency; if (take_money_from_dungeon(calltng->owner, crstat->scavenger_cost, 1) < 0) { ERRORLOG("Cannot take %d gold from dungeon %d",(int)crstat->scavenger_cost,(int)calltng->owner); } create_price_effect(&calltng->mappos, calltng->owner, crstat->scavenger_cost); } return 0; }
long creature_move_direct_line_backwards(struct Thing *thing, struct Coord3d *nextpos, MoveSpeed speed) { if (creature_turn_to_face_backwards(thing, nextpos) > 0) { // Creature is turning - don't let it move creature_set_speed(thing, 0); return 2; } struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); creature_set_speed(thing, -speed); cctrl->flgfield_2 |= TF2_Unkn01; if (get_2d_box_distance(&thing->mappos, nextpos) > -2*cctrl->move_speed) { ERRORDBG(3,"The %s index %d tried to reach (%d,%d) from (%d,%d) with excessive backward speed", thing_model_name(thing),(int)thing->index,(int)nextpos->x.stl.num,(int)nextpos->y.stl.num, (int)thing->mappos.x.stl.num,(int)thing->mappos.y.stl.num); cctrl->moveaccel.x.val = distance_with_angle_to_coord_x(cctrl->move_speed, thing->move_angle_xy); cctrl->moveaccel.y.val = distance_with_angle_to_coord_y(cctrl->move_speed, thing->move_angle_xy); cctrl->moveaccel.z.val = 0; return 1; } else { cctrl->moveaccel.x.val = nextpos->x.val - (MapCoordDelta)thing->mappos.x.val; cctrl->moveaccel.y.val = nextpos->y.val - (MapCoordDelta)thing->mappos.y.val; cctrl->moveaccel.z.val = 0; return 0; } }
short at_workshop_room(struct Thing *thing) { struct CreatureControl *cctrl; struct Room *room; //return _DK_at_workshop_room(thing); cctrl = creature_control_get_from_thing(thing); cctrl->target_room_id = 0; room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_WORKSHOP, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing)); set_start_state(thing); return 0; } if (room->total_capacity <= room->used_capacity) { set_start_state(thing); return 0; } if ( !add_creature_to_work_room(thing, room) ) { set_start_state(thing); return 0; } internal_set_thing_state(thing, CrSt_Manufacturing); setup_move_to_new_workshop_position(thing, room, 1); return 1; }
/** * Does a step of being imprisoned. * Informs if the imprisoning cycle should end. * @param thing */ CrCheckRet process_prison_function(struct Thing *creatng) { struct Room *room; room = get_room_creature_works_in(creatng); if (!room_still_valid_as_type_for_thing(room, RoK_PRISON, creatng)) { WARNLOG("Room %s owned by player %d is bad work place for %s index %d owner %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); set_start_state(creatng); return CrCkRet_Continue; } process_creature_hunger(creatng); if ( process_prisoner_skelification(creatng,room) ) return CrCkRet_Deleted; struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if ((cctrl->instance_id == CrInst_NULL) && process_prison_food(creatng, room) ) return CrCkRet_Continue; // Breaking from jail is only possible once per some amount of turns if ((game.play_gameturn % gameadd.time_between_prison_break) == 0) { if (jailbreak_possible(room, creatng->owner)) { if (is_my_player_number(room->owner)) output_message(SMsg_PrisonersEscaping, 40, true); else if (is_my_player_number(room->owner)) output_message(SMsg_CreatrFreedPrison, 40, true); set_start_state(creatng); return CrCkRet_Continue; } } return CrCkRet_Available; }
TbBool prison_convert_creature_to_skeleton(struct Room *room, struct Thing *thing) { struct Dungeon *dungeon; struct CreatureControl *cctrl; struct Thing *crthing; long crmodel; cctrl = creature_control_get_from_thing(thing); crmodel = get_room_create_creature_model(room->kind); // That normally returns skeleton breed crthing = create_creature(&thing->mappos, crmodel, room->owner); if (thing_is_invalid(crthing)) { ERRORLOG("Couldn't create creature %s in prison", creature_code_name(crmodel)); return false; } init_creature_level(crthing, cctrl->explevel); set_start_state(crthing); if (creature_model_bleeds(thing->model)) create_effect_around_thing(thing, TngEff_Unknown10); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); dungeon = get_dungeon(room->owner); if (!dungeon_invalid(dungeon)) { dungeon->lvstats.skeletons_raised++; } return true; }
CrStateRet process_prison_visuals(struct Thing *thing, struct Room *room) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (cctrl->instance_id != CrInst_NULL) { return CrStRet_Unchanged; } if (game.play_gameturn - cctrl->field_82 > 200) { if (game.play_gameturn - cctrl->field_82 < 250) { set_creature_instance(thing, CrInst_MOAN, 1, 0, 0); if (game.play_gameturn - cctrl->last_mood_sound_turn > 32) { play_creature_sound(thing, CrSnd_Sad, 2, 0); cctrl->last_mood_sound_turn = game.play_gameturn; } return CrStRet_Modified; } cctrl->field_82 = game.play_gameturn; } if (setup_prison_move(thing, room)) { return CrStRet_Modified; } return CrStRet_Unchanged; }
short move_to_position(struct Thing *creatng) { CreatureStateCheck callback; struct CreatureControl *cctrl; struct StateInfo *stati; long move_result; CrCheckRet state_check; long speed; TRACE_THING(creatng); cctrl = creature_control_get_from_thing(creatng); speed = get_creature_speed(creatng); SYNCDBG(18,"Starting to move %s index %d into (%d,%d)",thing_model_name(creatng),(int)creatng->index,(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num); // Try teleporting the creature if (creature_move_to_using_teleport(creatng, &cctrl->moveto_pos, speed)) { SYNCDBG(8,"Teleporting %s index %d owner %d into (%d,%d) for %s",thing_model_name(creatng),(int)creatng->index,(int)creatng->owner, (int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num,creature_state_code_name(creatng->continue_state)); return 1; } move_result = creature_move_to(creatng, &cctrl->moveto_pos, speed, cctrl->move_flags, 0); state_check = CrCkRet_Available; stati = get_thing_continue_state_info(creatng); if (!state_info_invalid(stati)) { callback = stati->move_check; if (callback != NULL) { SYNCDBG(18,"Doing move check callback for continue state %s",creature_state_code_name(creatng->continue_state)); state_check = callback(creatng); } } if (state_check == CrCkRet_Available) { // If moving was successful if (move_result == 1) { // Back to "main state" internal_set_thing_state(creatng, creatng->continue_state); return CrStRet_Modified; } // If moving failed, do a reset if (move_result == -1) { CrtrStateId cntstat; cntstat = creatng->continue_state; internal_set_thing_state(creatng, cntstat); set_start_state(creatng); SYNCDBG(8,"Couldn't move %s to place required for state %s; reset to state %s",thing_model_name(creatng),creature_state_code_name(cntstat),creatrtng_actstate_name(creatng)); return CrStRet_ResetOk; } // If continuing the job, check for job stress process_job_stress_and_going_postal(creatng); } switch (state_check) { case CrCkRet_Deleted: return CrStRet_Deleted; case CrCkRet_Available: return CrStRet_Modified; default: return CrStRet_ResetOk; } }
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; }
TbBool setup_person_move_to_position_f(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y, NaviRouteFlags flags, const char *func_name) { struct CreatureControl *cctrl; struct Coord3d locpos; SYNCDBG(18,"%s: Moving %s index %d to (%d,%d)",func_name,thing_model_name(thing),(int)thing->index,(int)stl_x,(int)stl_y); TRACE_THING(thing); locpos.x.val = subtile_coord_center(stl_x); locpos.y.val = subtile_coord_center(stl_y); locpos.z.val = thing->mappos.z.val; locpos.z.val = get_thing_height_at(thing, &locpos); cctrl = creature_control_get_from_thing(thing); if (creature_control_invalid(cctrl)) { WARNLOG("%s: Tried to move invalid creature to (%d,%d)",func_name,(int)stl_x,(int)stl_y); return false; } if (thing_in_wall_at(thing, &locpos)) { SYNCDBG(16,"%s: The %s would be trapped in wall at (%d,%d)",func_name,thing_model_name(thing),(int)stl_x,(int)stl_y); return false; } if (!creature_can_navigate_to_with_storage_f(thing, &locpos, flags, func_name)) { SYNCDBG(19,"%s: The %s cannot reach subtile (%d,%d)",func_name,thing_model_name(thing),(int)stl_x,(int)stl_y); return false; } cctrl->move_flags = flags; internal_set_thing_state(thing, CrSt_MoveToPosition); cctrl->moveto_pos.x.val = locpos.x.val; cctrl->moveto_pos.y.val = locpos.y.val; cctrl->moveto_pos.z.val = locpos.z.val; SYNCDBG(19,"%s: Done",func_name); return true; }
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; }
CrStateRet guarding(struct Thing *thing) { struct Room *room; TRACE_THING(thing); room = get_room_thing_is_on(thing); if (creature_job_in_room_no_longer_possible(room, Job_GUARD, thing)) { remove_creature_from_work_room(thing); set_start_state(thing); return CrStRet_ResetFail; } struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (creature_move_to(thing, &cctrl->moveto_pos, cctrl->max_speed, 0, 0) == 0) { return CrStRet_Unchanged; } if (!person_get_somewhere_adjacent_in_room(thing, room, &cctrl->moveto_pos)) { cctrl->moveto_pos.x.val = thing->mappos.x.val; cctrl->moveto_pos.y.val = thing->mappos.y.val; cctrl->moveto_pos.z.val = thing->mappos.z.val; } return CrStRet_Modified; }
void clear_creature_instance(struct Thing *thing) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); cctrl->instance_id = CrInst_NULL; cctrl->inst_turn = 0; }
short at_scavenger_room(struct Thing *thing) { struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Dungeon *dungeon; struct Room *room; //return _DK_at_scavenger_room(thing); room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_SCAVENGER, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index); set_start_state(thing); return 0; } cctrl = creature_control_get_from_thing(thing); crstat = creature_stats_get_from_thing(thing); dungeon = get_dungeon(thing->owner); if (crstat->scavenger_cost >= dungeon->total_money_owned) { if (is_my_player_number(thing->owner)) output_message(SMsg_NoGoldToScavenge, MESSAGE_DELAY_TREASURY, true); set_start_state(thing); return 0; } if (!add_creature_to_work_room(thing, room)) { set_start_state(thing); return 0; } internal_set_thing_state(thing, CrSt_Scavengering); cctrl->field_82 = 0; return 1; }
void transfer_creature(struct Thing *boxtng, struct Thing *transftng, unsigned char plyr_idx) { SYNCDBG(7,"Starting"); struct CreatureControl *cctrl; if (!thing_exists(boxtng) || (box_thing_to_special(boxtng) != SpcKind_TrnsfrCrtr) ) { ERRORMSG("Invalid transfer box object!"); return; } // Check if 'things' are correct if (!thing_exists(transftng) || !thing_is_creature(transftng) || (transftng->owner != plyr_idx)) { ERRORMSG("Invalid transfer creature thing!"); return; } cctrl = creature_control_get_from_thing(transftng); set_transfered_creature(plyr_idx, transftng->model, cctrl->explevel); remove_thing_from_power_hand_list(transftng, plyr_idx); kill_creature(transftng, INVALID_THING, -1, CrDed_NoEffects|CrDed_NotReallyDying); create_special_used_effect(&boxtng->mappos, plyr_idx); remove_events_thing_is_attached_to(boxtng); force_any_creature_dragging_owned_thing_to_drop_it(boxtng); delete_thing_structure(boxtng, 0); if (is_my_player_number(plyr_idx)) output_message(SMsg_CommonAcknowledge, 0, true); }
TbBool send_creature_to_job_near_position(struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, CreatureJob new_job) { SYNCDBG(6,"Starting for %s (owner %d) and job %s",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job)); struct CreatureJobConfig *jobcfg; jobcfg = get_config_for_job(new_job); if (jobcfg->func_cord_assign != NULL) { if (jobcfg->func_cord_assign(creatng, stl_x, stl_y, new_job)) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); // Set computer control accordingly to job flags if ((get_flags_for_job(new_job) & JoKF_NoSelfControl) != 0) { cctrl->flgfield_1 |= CCFlg_NoCompControl; } else { cctrl->flgfield_1 &= ~CCFlg_NoCompControl; } // If a new task isn't a work-in-group thing, remove the creature from group if ((get_flags_for_job(new_job) & JoKF_NoGroups) != 0) { if (creature_is_group_member(creatng)) { remove_creature_from_group(creatng); } } return true; } } else { ERRORLOG("Cannot start %s for %s (owner %d); job has no coord-based assign",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->owner); } return false; }
long instf_damage_wall(struct Thing *creatng, long *param) { SYNCDBG(16,"Starting"); TRACE_THING(creatng); //return _DK_instf_damage_wall(creatng, param); MapSubtlCoord stl_x, stl_y; { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); stl_x = stl_num_decode_x(cctrl->field_284); stl_y = stl_num_decode_y(cctrl->field_284); } struct SlabMap *slb; slb = get_slabmap_for_subtile(stl_x, stl_y); if (slb->health > 2) { slb->health -= 2; } else { place_slab_type_on_map(2, stl_x, stl_y, creatng->owner, 0); do_slab_efficiency_alteration(subtile_slab_fast(stl_x), subtile_slab_fast(stl_y)); } thing_play_sample(creatng, 63+UNSYNC_RANDOM(6), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return 1; }
TbBool attempt_job_sleep_in_lair_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; } cctrl->slap_turns = 0; cctrl->max_speed = calculate_correct_creature_maxspeed(creatng); if (creature_has_lair_room(creatng) && (room->index == cctrl->lair_room_id)) { if (creature_move_to_home_lair(creatng)) { creatng->continue_state = CrSt_CreatureGoingHomeToSleep; return 1; } } struct Coord3d pos; if (find_first_valid_position_for_thing_in_room(creatng, room, &pos) && setup_person_move_to_coord(creatng, &pos, NavRtF_Default)) { creatng->continue_state = CrSt_CreatureChangeLair; cctrl->target_room_id = room->index; return 1; } return 0; }
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; }