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 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); }
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; }
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; }
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; }
/** Returns if a creature can do specific job for the player. * * @param creatng The creature which is planned for the job. * @param plyr_idx Player for whom the job is to be done. * @param new_job Job selection with single job flag set. * @param flags Function behavior adjustment flags. * @return True if the creature can do the job specified, false otherwise. * @note this should be used instead of person_will_do_job_for_room() * @note this function will never change state of the input thing, even if appropriate flags are set * @see creature_can_do_job_near_position() similar function for use when target position is known */ TbBool creature_can_do_job_for_player(const struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job, unsigned long flags) { SYNCDBG(16,"Starting for %s (owner %d) and job %s",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job)); if (creature_will_reject_job(creatng, new_job)) { SYNCDBG(13,"Cannot assign %s for %s index %d owner %d; in not do jobs list",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); return false; } if (!is_correct_owner_to_perform_job(creatng, plyr_idx, new_job)) { SYNCDBG(13,"Cannot assign %s for %s index %d owner %d; not correct owner for job",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); return false; } // Don't allow creatures changed to chickens to have any job assigned, besides those specifically marked if (creature_affected_by_spell(creatng, SplK_Chicken) && ((get_flags_for_job(new_job) & JoKF_AllowChickenized) == 0)) { SYNCDBG(13,"Cannot assign %s for %s index %d owner %d; under chicken spell",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); return false; } // Check if the job is related to correct player struct CreatureJobConfig *jobcfg; jobcfg = get_config_for_job(new_job); if (jobcfg->func_plyr_check == NULL) { return false; } if (!jobcfg->func_plyr_check(creatng, plyr_idx, new_job)) { return false; } RoomKind job_rkind; job_rkind = get_room_for_job(new_job); if (job_rkind != RoK_NONE) { if (!player_has_room(plyr_idx, job_rkind)) { SYNCDBG(3,"Cannot assign %s in player %d room for %s index %d owner %d; no required room built",creature_job_code_name(new_job),(int)plyr_idx,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); if ((flags & JobChk_PlayMsgOnFail) != 0) { const struct RoomConfigStats *roomst; roomst = get_room_kind_stats(get_room_for_job(new_job)); if (is_my_player_number(plyr_idx) && (roomst->msg_needed > 0)) { output_message_room_related_from_computer_or_player_action(roomst->msg_needed); } } return false; } if ((get_flags_for_job(new_job) & JoKF_NeedsCapacity) != 0) { struct Room *room; room = find_room_with_spare_capacity(plyr_idx, job_rkind, 1); if (room_is_invalid(room)) { SYNCDBG(3,"Cannot assign %s in player %d room for %s index %d owner %d; not enough room capacity",creature_job_code_name(new_job),(int)plyr_idx,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); if ((flags & JobChk_PlayMsgOnFail) != 0) { const struct RoomConfigStats *roomst; roomst = get_room_kind_stats(get_room_for_job(new_job)); if (is_my_player_number(plyr_idx) && (roomst->msg_too_small > 0)) { output_message_room_related_from_computer_or_player_action(roomst->msg_too_small); } } return false; } } } return true; }