Esempio n. 1
0
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;
}
Esempio n. 2
0
/**
 * Processes job stress and going postal due to annoying co-workers.
 * Creatures which aren't performing their primary jobs can be attacked by creatures
 * going postal.
 * Creature doing primary job in room may go postal and attack other creatures walking
 * through the same room which aren't performing the same job (ie. are just passing by),
 * or other workers in that room who does not have the job as primary job.
 *
 * @param creatng The thing being affected by job stress or going postal.
 * @param room The room where target creature should be searched for.
 * @return
 */
TbBool process_job_stress_and_going_postal(struct Thing *creatng, struct Room *room)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    cctrl = creature_control_get_from_thing(creatng);
    crstat = creature_stats_get_from_thing(creatng);
    if (cctrl->instance_id != CrInst_NULL) {
        return false;
    }
    // Process the stress once per 20 turns
    //TODO CONFIG export amount of turns to config file
    if (((game.play_gameturn + creatng->index) % 20) != 0) {
        return false;
    }
    // Process the job stress
    if (crstat->annoy_job_stress != 0)
    {
        // Note that this kind of code won't allow one-time jobs, or jobs not related to rooms, to be stressful
        CreatureJob stressful_job;
        stressful_job = get_creature_job_causing_stress(crstat->job_stress,room->kind);
        if (stressful_job != Job_NULL)
        {
            anger_apply_anger_to_creature(creatng, crstat->annoy_job_stress, AngR_Other, 1);
        }
    }
    // Process going postal
    if (crstat->annoy_going_postal != 0)
    {
        // Make sure we really should go postal in that room
        CreatureJob going_postal_job;
        going_postal_job = get_creature_job_causing_going_postal(crstat->job_primary,room->kind);
        if (going_postal_job != Job_NULL)
        {
            if (process_job_causes_going_postal(creatng, room, going_postal_job)) {
                return true;
            }
        }
    }
    return false;
}
Esempio n. 3
0
TbBool process_job_causes_going_postal(struct Thing *creatng, struct Room *room, CreatureJob going_postal_job)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    cctrl = creature_control_get_from_thing(creatng);
    crstat = creature_stats_get_from_thing(creatng);
    CrInstance inst_use;
    inst_use = get_best_quick_range_instance_to_use(creatng);
    if (inst_use <= 0) {
        return false;
    }
    // Find a target
    unsigned long combt_dist;
    struct Thing *combt_thing;
    combt_dist = LONG_MAX;
    combt_thing = INVALID_THING;
    if (find_combat_target_passing_by_room_but_having_unrelated_job(creatng, going_postal_job, room, &combt_dist, &combt_thing))
    {
        struct CreatureControl *combctrl;
        set_creature_instance(creatng, inst_use, 0, combt_thing->index, 0);
        external_set_thing_state(combt_thing, CrSt_CreatureEvacuateRoom);
        combctrl = creature_control_get_from_thing(combt_thing);
        combctrl->word_9A = room->index;
        anger_apply_anger_to_creature(creatng, crstat->annoy_going_postal, AngR_Other, 1);
        return true;
    }
    if (thing_is_invalid(combt_thing)) {
        return false;
    }
    if (!setup_person_move_to_coord(creatng, &combt_thing->mappos, NavRtF_Default)) {
        return false;
    }
    //TODO this is weak - going postal may be used in other rooms
    creatng->continue_state = CrSt_Researching;
    cctrl->field_82 = 0;
    cctrl->byte_9A = 3;
    return true;
}
Esempio n. 4
0
/** Returns if a creature can do specific job at given map position.
*
* @param creatng The creature which is planned for the job.
* @param stl_x Target map position, x coord.
* @param stl_y Target map position, y coord.
* @param new_job Job selection with single job flag set.
* @return True if the creature can do the job specified, false otherwise.
* @see creature_can_do_job_for_player() similar function for use when only target player is known
*/
TbBool creature_can_do_job_near_position(struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, CreatureJob new_job, unsigned long flags)
{
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    SYNCDBG(6,"Starting for %s (owner %d) and job %s",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job));
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    if (creature_will_reject_job(creatng, new_job))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; in not-do-jobs list",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        if ((flags & JobChk_SetStateOnFail) != 0) {
            anger_apply_anger_to_creature(creatng, crstat->annoy_will_not_do_job, AngR_Other, 1);
            external_set_thing_state(creatng, CrSt_CreatureMoan);
            cctrl->field_282 = 50;
        }
        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(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; under chicken spell",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    // Check if the job is related to correct map place (room,slab)
    if (!is_correct_position_to_perform_job(creatng, stl_x, stl_y, new_job))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; not correct place for job",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    struct CreatureJobConfig *jobcfg;
    jobcfg = get_config_for_job(new_job);
    if (jobcfg->func_cord_check == NULL)
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; job has no coord check function",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    if (!jobcfg->func_cord_check(creatng, stl_x, stl_y, new_job, flags))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; coord check not passed",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    // If other tests pass, check if related room (if is needed) has capacity to be used for that job
    if ((get_flags_for_job(new_job) & JoKF_NeedsCapacity) != 0)
    {
        struct Room *room;
        room = subtile_room_get(stl_x, stl_y);
        if (!room_has_enough_free_capacity_for_creature(room, creatng))
        {
            SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; not enough room capacity",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
            if ((flags & JobChk_PlayMsgOnFail) != 0) {
                const struct RoomConfigStats *roomst;
                roomst = get_room_kind_stats(room->kind);
                if (is_my_player_number(room->owner) && (roomst->msg_too_small > 0)) {
                    output_message_room_related_from_computer_or_player_action(roomst->msg_too_small);
                }
            }
            return false;
        }
    }
    return true;
}