long creature_turn_to_face(struct Thing *thing, const struct Coord3d *pos)
{
    //TODO enable when issue in pathfinding is solved
    /*if (get_2d_box_distance(&thing->mappos, pos) <= 0)
        return -1;*/
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(thing);
    long angle;
    angle = get_angle_xy_to(&thing->mappos, pos);
    long angle_diff, angle_sign, angle_delta;
    angle_diff = get_angle_difference(thing->move_angle_xy, angle);
    angle_sign = get_angle_sign(thing->move_angle_xy, angle);
    angle_delta = crstat->max_angle_change;
    if (angle_delta < 1) {
        angle_delta = 1;
    }
    if (angle_delta > angle_diff) {
        angle_delta = angle_diff;
    }
    if (angle_sign < 0) {
        angle_delta = -angle_delta;
    }
    long i;
    i = (thing->move_angle_xy + angle_delta);
    thing->move_angle_xy = i & LbFPMath_AngleMask;
    return get_angle_difference(thing->move_angle_xy, angle);
}
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;
}
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;
}
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;
}
示例#5
0
struct Thing *create_and_control_creature_as_controller(struct PlayerInfo *player, long breed, struct Coord3d *pos)
{
    struct CreatureStats *crstat;
    struct CreatureControl *cctrl;
    struct Dungeon *dungeon;
    struct Thing *thing;
    struct Camera *cam;
    struct InitLight ilght;
    SYNCDBG(6,"Request for model %ld at (%d,%d,%d)",breed,(int)pos->x.val,(int)pos->y.val,(int)pos->z.val);
    //return _DK_create_and_control_creature_as_controller(player, a2, pos);
    thing = create_creature(pos, breed, player->id_number);
    if (thing_is_invalid(thing))
      return INVALID_THING;
    dungeon = get_dungeon(thing->owner);
    dungeon->num_active_creatrs--;
    dungeon->owned_creatures_of_model[thing->model]--;
    if (is_my_player(player))
    {
        toggle_status_menu(0);
        turn_off_roaming_menus();
    }
    cam = player->acamera;
    player->controlled_thing_idx = thing->index;
    player->field_31 = thing->creation_turn;
    player->field_4B5 = cam->field_6;
    thing->alloc_flags |= TAlF_IsControlled;
    thing->field_4F |= 0x01;
    cctrl = creature_control_get_from_thing(thing);
    cctrl->flgfield_2 |= 0x02;
    cctrl->max_speed = calculate_correct_creature_maxspeed(thing);
    set_player_mode(player, PVT_CreatureContrl);
    set_start_state(thing);
    // Preparing light object
    LbMemorySet(&ilght, 0, sizeof(struct InitLight));
    ilght.mappos.x.val = thing->mappos.x.val;
    ilght.mappos.y.val = thing->mappos.y.val;
    ilght.mappos.z.val = thing->mappos.z.val;
    ilght.field_2 = 36;
    ilght.field_3 = 1;
    ilght.is_dynamic = 1;
    ilght.field_0 = 2560;
    thing->light_id = light_create_light(&ilght);
    if (thing->light_id != 0)
    {
        light_set_light_never_cache(thing->light_id);
    } else
    {
        ERRORLOG("Cannot allocate light to new hero");
    }
    if (is_my_player_number(thing->owner))
    {
        if (thing->class_id == TCls_Creature)
        {
            crstat = creature_stats_get_from_thing(thing);
            setup_eye_lens(crstat->eye_effect);
        }
    }
    return thing;
}
/**
 * Returns if a creature can currently travel over lava.
 * @param thing
 * @return
 */
TbBool creature_can_travel_over_lava(const struct Thing *creatng)
{
    const struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    // Check if a creature can fly in this moment - we don't care if it's natural ability
    // or temporary spell effect
    return (crstat->hurt_by_lava <= 0) || ((creatng->movement_flags & TMvF_Flying) != 0);
}
/**
 * Returns if a player to whom the creature belongs can afford the creature to go scavenging.
 * @param creatng
 * @return
 */
TbBool player_can_afford_to_scavenge_creature(const struct Thing *creatng)
{
    struct Dungeon *dungeon;
    dungeon = get_dungeon(creatng->owner);
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    return (crstat->scavenger_cost < dungeon->total_money_owned);
}
示例#8
0
/**
 *
 * @param creatng
 * @param plyr_idx
 * @param rkind
 * @return
 * @deprecated Room does not correspond to single job anymore, this should be avoided.
 */
TbBool creature_can_do_job_for_computer_player_in_room(const struct Thing *creatng, PlayerNumber plyr_idx, RoomKind rkind)
{
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    CreatureJob jobpref;
    jobpref = get_job_for_room(rkind, JoKF_AssignComputerDropInRoom, crstat->job_primary|crstat->job_secondary);
    return creature_can_do_job_for_player(creatng, plyr_idx, jobpref, JobChk_None);
}
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;
}
示例#10
0
long creature_add_lair_to_room(struct Thing *creatng, struct Room *room)
{
    struct Thing *lairtng;
    if (!room_has_enough_free_capacity_for_creature(room, creatng))
        return 0;
    //return _DK_creature_add_lair_to_room(thing, room);
    // Make sure we don't already have a lair on that position
    lairtng = find_creature_lair_at_subtile(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, 0);
    if (!thing_is_invalid(lairtng))
        return 0;
    struct CreatureStats *crstat;
    struct CreatureControl *cctrl;
    crstat = creature_stats_get_from_thing(creatng);
    cctrl = creature_control_get_from_thing(creatng);
    room->content_per_model[creatng->model]++;
    room->used_capacity += crstat->lair_size;
    if ((cctrl->lair_room_id > 0) && (cctrl->lairtng_idx > 0))
    {
        struct Room *room;
        room = room_get(cctrl->lair_room_id);
        creature_remove_lair_from_room(creatng, room);
    }
    cctrl->lair_room_id = room->index;
    // Create the lair thing
    struct CreatureData *crdata;
    struct Coord3d pos;
    pos.x.val = creatng->mappos.x.val;
    pos.y.val = creatng->mappos.y.val;
    pos.z.val = creatng->mappos.z.val;
    crdata = creature_data_get_from_thing(creatng);
    lairtng = create_object(&pos, crdata->field_1, creatng->owner, -1);
    if (thing_is_invalid(lairtng))
    {
        ERRORLOG("Could not create lair totem");
        remove_thing_from_mapwho(creatng);
        place_thing_in_mapwho(creatng);
        return 1; // Return that so we won't try to redo the action over and over
    }
    lairtng->mappos.z.val = get_thing_height_at(lairtng, &lairtng->mappos);
    // Associate creature with the lair
    cctrl->lairtng_idx = lairtng->index;
    lairtng->word_13 = creatng->index;
    lairtng->word_15 = 1;
    // Lair size depends on creature level
    lairtng->word_17 = 300 * cctrl->explevel / 20 + 300;
    lairtng->field_52 = ACTION_RANDOM(0x800);
    struct Objects *objdat;
    unsigned long i;
    objdat = get_objects_data_for_thing(lairtng);
    i = convert_td_iso(objdat->field_5);
    set_thing_draw(lairtng, i, objdat->field_7, lairtng->word_15, 0, -1, objdat->field_11);
    thing_play_sample(creatng, 158, NORMAL_PITCH, 0, 3, 1, 2, FULL_LOUDNESS);
    create_effect(&pos, imp_spangle_effects[creatng->owner], creatng->owner);
    anger_set_creature_anger(creatng, 0, AngR_NoLair);
    remove_thing_from_mapwho(creatng);
    place_thing_in_mapwho(creatng);
    return 1;
}
示例#11
0
TbBool player_can_afford_to_train_creature(const struct Thing *thing)
{
    struct Dungeon *dungeon;
    struct CreatureStats *crstat;
    //return _DK_player_can_afford_to_train_creature(thing);
    dungeon = get_dungeon(thing->owner);
    crstat = creature_stats_get_from_thing(thing);
    return (dungeon->total_money_owned >= crstat->training_cost);
}
示例#12
0
TbBool creature_can_do_scavenging(const struct Thing *creatng)
{
    if (is_neutral_thing(creatng)) {
        return false;
    }
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    return (crstat->scavenge_value > 0);
}
示例#13
0
/**
 * Returns if given creature is able to heal by sleeping.
 * Does not take into consideration if the creature has a lair, checks only if
 * the creature model is able to heal in its lair in general.
 * @param creatng
 * @return
 */
TbBool creature_can_do_healing_sleep(const struct Thing *creatng)
{
    if (is_neutral_thing(creatng)) {
        return false;
    }
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    return ((crstat->heal_requirement > 0) && (crstat->lair_size > 0));
}
示例#14
0
TbBool creature_can_do_research(const struct Thing *creatng)
{
    if (is_neutral_thing(creatng)) {
        return false;
    }
    struct CreatureStats *crstat;
    struct Dungeon *dungeon;
    crstat = creature_stats_get_from_thing(creatng);
    dungeon = get_dungeon(creatng->owner);
    return (crstat->research_value > 0) && (dungeon->current_research_idx >= 0);
}
示例#15
0
/** Returns if the creature meets conditions to be trained.
 *
 * @param thing The creature thing to be tested.
 * @return
 */
TbBool creature_can_be_trained(const struct Thing *thing)
{
    struct CreatureStats *crstat;
    //return _DK_creature_can_be_trained(thing);
    crstat = creature_stats_get_from_thing(thing);
    // Creatures without training value can't be trained
    if (crstat->training_value <= 0)
        return false;
    // If its model can train, check if this one can gain more experience
    return creature_can_gain_experience(thing);
}
示例#16
0
TbBool creature_try_doing_secondary_job(struct Thing *creatng)
{
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    if (game.play_gameturn - cctrl->job_secondary_check_turn <= 128) {
        return false;
    }
    cctrl->job_secondary_check_turn = game.play_gameturn;
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    return attempt_job_secondary_preference(creatng, crstat->job_secondary);
}
示例#17
0
TbBool creature_requires_healing(const struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    cctrl = creature_control_get_from_thing(thing);
    crstat = creature_stats_get_from_thing(thing);
    long maxhealth, minhealth;
    maxhealth = compute_creature_max_health(crstat->health,cctrl->explevel);
    minhealth = crstat->heal_requirement * maxhealth / 256;
    if ((long)thing->health <= minhealth)
        return true;
    return false;
}
示例#18
0
TbBool process_prisoner_skelification(struct Thing *thing, struct Room *room)
{
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(thing);
    if ((thing->health >= 0) || (!crstat->humanoid_creature)) {
        return false;
    }
    //TODO [config] Allow skeletification only if spent specific amount of turns in prison (set low value)
    if (ACTION_RANDOM(101) > game.prison_skeleton_chance)
      return false;
    if (is_my_player_number(room->owner))
      output_message(SMsg_PrisonMadeSkeleton, 0, true);
    prison_convert_creature_to_skeleton(room,thing);
    return true;
}
示例#19
0
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);
    }
}
示例#20
0
TbBool creature_can_gain_experience(const struct Thing *thing)
{
    struct Dungeon *dungeon;
    struct CreatureStats *crstat;
    struct CreatureControl *cctrl;
    dungeon = get_dungeon(thing->owner);
    cctrl = creature_control_get_from_thing(thing);
    // Creatures which reached players max level can't be trained
    if (cctrl->explevel >= dungeon->creature_max_level[thing->model])
        return false;
    // Creatures which reached absolute max level and have no grow up creature
    crstat = creature_stats_get_from_thing(thing);
    if ((cctrl->explevel >= (CREATURE_MAX_LEVEL-1)) && (crstat->grow_up == 0))
        return false;
    return true;
}
示例#21
0
short manufacturing(struct Thing *creatng)
{
    struct Room *room;
    //return _DK_manufacturing(creatng);
    TRACE_THING(creatng);
    room = get_room_thing_is_on(creatng);
    if (creature_work_in_room_no_longer_possible(room, RoK_WORKSHOP, creatng))
    {
        remove_creature_from_work_room(creatng);
        set_start_state(creatng);
        return CrStRet_ResetFail;
    }
    if (room->used_capacity > room->total_capacity)
    {
        if (is_my_player_number(creatng->owner))
            output_message(SMsg_WorkshopTooSmall, 500, true);
        remove_creature_from_work_room(creatng);
        set_start_state(creatng);
        return CrStRet_ResetOk;
    }
    struct Dungeon *dungeon;
    dungeon = get_dungeon(creatng->owner);
    if (dungeon->manufacture_class)
    {
        struct CreatureControl *cctrl;
        struct CreatureStats *crstat;
        cctrl = creature_control_get_from_thing(creatng);
        crstat = creature_stats_get_from_thing(creatng);
        long work_value;
        work_value = compute_creature_work_value(crstat->manufacture_value*256, room->efficiency, cctrl->explevel);
        work_value = process_work_speed_on_work_value(creatng, work_value);
        SYNCDBG(9,"The %s index %d produced %d manufacture points",thing_model_name(creatng),(int)creatng->index,(int)work_value);
        dungeon->manufacture_progress += work_value;
        dungeon->field_1181 += work_value;
    } else
    {
        WARNDBG(9,"The %s index %d owner %d is manufacturing nothing",thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        // This may be cause by a creature taking up place in workshop where crate should be created; the creature should take a break
        if (room->used_capacity >= room->total_capacity) {
            external_set_thing_state(creatng, CrSt_CreatureGoingHomeToSleep);
            return CrStRet_Modified;
        }
    }
    process_creature_in_workshop(creatng, room);
    return CrStRet_Modified;
}
示例#22
0
void creature_increase_available_instances(struct Thing *thing)
{
    struct CreatureStats *crstat;
    struct CreatureControl *cctrl;
    crstat = creature_stats_get_from_thing(thing);
    cctrl = creature_control_get_from_thing(thing);
    int i,k;
    for (i=0; i < CREATURE_MAX_LEVEL; i++)
    {
        k = crstat->instance_spell[i];
        if (k > 0)
        {
            if (crstat->instance_level[i] <= cctrl->explevel+1) {
                cctrl->instance_available[k] = true;
            }
        }
    }
}
示例#23
0
TbBool creature_find_and_perform_anger_job(struct Thing *creatng)
{
    //return _DK_creature_find_and_perform_anger_job(creatng);
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    int i, k, n;
    // Count the amount of jobs set
    i = 0;
    k = crstat->jobs_anger;
    while (k != 0)
    {
        if ((k & 1) != 0)
            i++;
        k >>= 1;
    }
    if (i <= 0) {
        return false;
    }
    // Select a random job as a starting point
    n = ACTION_RANDOM(i) + 1;
    i = 0;
    for (k = 0; k < crtr_conf.angerjobs_count; k++)
    {
        if ((crstat->jobs_anger & (1 << k)) != 0) {
            n--;
        }
        if (n <= 0) {
            i = k;
            break;
        }
    }
    // Go through all jobs, starting at randomly selected one, attempting to start each one
    for (k = 0; k < crtr_conf.angerjobs_count; k++)
    {
        if ((crstat->jobs_anger & (1 << i)) != 0)
        {
            if (attempt_anger_job(creatng, 1 << i))
                return 1;
        }
        i = (i+1) % crtr_conf.angerjobs_count;
    }
    return 0;
}
示例#24
0
short at_training_room(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    struct Dungeon *dungeon;
    struct Room *room;
    //return _DK_at_training_room(thing);
    cctrl = creature_control_get_from_thing(thing);
    cctrl->target_room_id = 0;
    if (!creature_can_be_trained(thing))
    {
        SYNCDBG(9,"Ending training of %s level %d; creature is not trainable",thing_model_name(thing),(int)cctrl->explevel);
        set_start_state(thing);
        return 0;
    }
    crstat = creature_stats_get_from_thing(thing);
    dungeon = get_dungeon(thing->owner);
    if (dungeon->total_money_owned < crstat->training_cost)
    {
        if (is_my_player_number(thing->owner))
            output_message(SMsg_NoGoldToTrain, MESSAGE_DELAY_TREASURY, true);
        set_start_state(thing);
        return 0;
    }
    room = get_room_thing_is_on(thing);
    if (!room_initially_valid_as_type_for_thing(room, RoK_TRAINING, 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 ( !add_creature_to_work_room(thing, room) )
    {
        set_start_state(thing);
        return 0;
    }
    internal_set_thing_state(thing, CrSt_Training);
    setup_move_to_new_training_position(thing, room, 1);
    cctrl->field_82 = 0;
    return 1;
}
示例#25
0
/**
 * Given instance ID, returns its position in compacted list of instances.
 * Compacted list of instances is a list of available creature instances without holes.
 * @param thing
 * @param req_inst_id
 * @return
 */
int creature_instance_get_available_pos_for_id(struct Thing *thing, CrInstance req_inst_id)
{
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(thing);
    int avail_pos;
    avail_pos = 0;
    int avail_num;
    for (avail_num = 0; avail_num < CREATURE_MAX_SPELL; avail_num++)
    {
        CrInstance inst_id;
        inst_id = crstat->instance_spell_id[avail_num];
        if (creature_instance_is_available(thing, inst_id))
        {
            if (inst_id == req_inst_id) {
                return avail_pos;
            }
            avail_pos++;
        }
    }
    return -1;
}
示例#26
0
/**
 * For position in compacted list of instances, gives instance ID from availability list.
 * Compacted list of instances is a list of available creature instances without holes.
 * @param thing
 * @param req_avail_pos
 * @return
 */
CrInstance creature_instance_get_available_id_for_pos(struct Thing *thing, int req_avail_pos)
{
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(thing);
    int avail_pos;
    avail_pos = 0;
    int avail_num;
    for (avail_num=0; avail_num < CREATURE_MAX_LEVEL; avail_num++)
    {
        CrInstance inst_id;
        inst_id = crstat->instance_spell[avail_num];
        if (creature_instance_is_available(thing, inst_id))
        {
            if (avail_pos == req_avail_pos) {
                return inst_id;
            }
            avail_pos++;
        }
    }
    return CrInst_NULL;
}
示例#27
0
TbBool creature_choose_first_available_instance(struct Thing *thing)
{
    struct CreatureStats *crstat;
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(thing);
    crstat = creature_stats_get_from_thing(thing);
    long i,k;
    for (i=0; i < CREATURE_MAX_LEVEL; i++)
    {
        k = crstat->instance_spell[i];
        if (k > 0)
        {
            if (cctrl->instance_available[k]) {
                cctrl->field_1E8 = k;
                return true;
            }
        }
    }
    cctrl->field_1E8 = 0;
    return false;
}
示例#28
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;
}
示例#29
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;
}
示例#30
0
TbBool attempt_anger_job_steal_gold(struct Thing *creatng)
{
    //return _DK_attempt_anger_job_steal_gold(creatng);
    if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreatureStealGold)) {
        return false;
    }
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    if (creatng->creature.gold_carried >= crstat->gold_hold) {
        return false;
    }
    struct Room *room;
    struct Coord3d pos;
    room = find_nearest_room_for_thing_with_used_capacity(creatng, creatng->owner, RoK_TREASURE, NavRtF_NoOwner, 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_CreatureStealGold)) {
        return false;
    }
    if (!setup_random_head_for_room(creatng, room, NavRtF_NoOwner))
    {
        ERRORLOG("Cannot setup head for treasury.");
        return false;
    }
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    creatng->continue_state = CrSt_CreatureSearchForGoldToStealInRoom1;
    cctrl->target_room_id = room->index;
    return true;
}