Esempio n. 1
0
TbBool attempt_job_secondary_preference(struct Thing *creatng, long jobpref)
{
    long i;
    unsigned long k;
    // Count the amount of jobs set
    i = 0;
    k = jobpref;
    while (k)
    {
        k >>= 1;
        i++;
    }
    if (i <= 0) {
        return false;
    }
    unsigned long select_val,select_curr,select_delta;
    select_val = ACTION_RANDOM(512);
    select_delta = 512 / i;
    select_curr = select_delta;
    // For some reason, this is a bit different than attempt_job_preference().
    // Probably needs unification
    for (i=1; i < crtr_conf.jobs_count; i++)
    {
        CreatureJob new_job = 1<<(i-1);
        if ((jobpref & new_job) == 0) {
            continue;
        }
        SYNCDBG(19,"Check job %s",creature_job_code_name(new_job));
        if (select_val <= select_curr)
        {
            select_curr += select_delta;
        } else if (creature_can_do_job_for_player(creatng, creatng->owner, new_job, JobChk_None))
        {
            if (send_creature_to_job_for_player(creatng, creatng->owner, new_job)) {
                return true;
            }
        }
    }
    // If no job, give 1% chance of going to temple
    if (ACTION_RANDOM(100) == 0)
    {
        CreatureJob new_job = Job_TEMPLE_PRAY;
        if (creature_can_do_job_for_player(creatng, creatng->owner, new_job, JobChk_None))
        {
            if (send_creature_to_job_for_player(creatng, creatng->owner, new_job)) {
                return true;
            }
        }
    }
    return 0;
}
Esempio n. 2
0
/**
 * Tries to assign one of creature's preferred jobs to it.
 * Starts at random job, to make sure all the jobs have equal chance of being selected.
 * @param creatng The creature to assign a job to.
 * @param jobpref Job preference flags.
 */
TbBool attempt_job_preference(struct Thing *creatng, long jobpref)
{
    //return _DK_attempt_job_preference(creatng, jobpref);
    long i,n;
    // Start checking at random job
    if (crtr_conf.jobs_count < 1) {
        return false;
    }
    n = ACTION_RANDOM(crtr_conf.jobs_count);
    for (i=0; i < crtr_conf.jobs_count; i++, n = (n+1)%crtr_conf.jobs_count)
    {
        if (n == 0)
            continue;
        CreatureJob new_job;
        new_job = 1 << (n-1);
        if ((jobpref & new_job) != 0)
        {
            SYNCDBG(19,"Check job %s",creature_job_code_name(new_job));
            if (creature_can_do_job_for_player(creatng, creatng->owner, new_job, JobChk_None))
            {
                if (send_creature_to_job_for_player(creatng, creatng->owner, new_job)) {
                    return true;
                }
            }
        }
    }
    return false;
}
Esempio n. 3
0
long computer_check_for_pretty(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    dungeon = comp->dungeon;
    MapSubtlCoord stl_x, stl_y;
    if (computer_able_to_use_magic(comp, PwrK_HAND, 1, 1) != CTaskRet_Unk1) {
        return CTaskRet_Unk4;
    }
    {
        long stack_len;
        stack_len = dungeon->digger_stack_length;
        if (stack_len <= check->param1 * dungeon->total_area / 100) {
            return CTaskRet_Unk4;
        }
        long n;
        n = find_in_imp_stack_starting_at(DigTsk_ImproveDungeon, ACTION_RANDOM(stack_len), dungeon);
        if (n < 0) {
            return CTaskRet_Unk4;
        }
        const struct DiggerStack *dstack;
        dstack = &dungeon->digger_stack[n];
        stl_x = stl_num_decode_x(dstack->stl_num);
        stl_y = stl_num_decode_y(dstack->stl_num);
    }
    struct Thing * creatng;
    creatng = find_imp_for_pickup(comp, stl_x, stl_y);
    if (thing_is_invalid(creatng)) {
        return CTaskRet_Unk4;
    }
    if (!create_task_move_creature_to_subtile(comp, creatng, stl_x, stl_y, CrSt_ImpImprovesDungeon)) {
        return CTaskRet_Unk4;
    }
    return CTaskRet_Unk1;
}
Esempio n. 4
0
TbBool attempt_anger_job_join_enemy(struct Thing *creatng)
{
    struct Thing *heartng;
    int i, n;
    n = ACTION_RANDOM(PLAYERS_COUNT);
    for (i=0; i < PLAYERS_COUNT; i++, n=(n+1)%PLAYERS_COUNT)
    {
        if ((n == game.neutral_player_num) || (n == creatng->owner))
            continue;
        struct PlayerInfo *player;
        player = get_player(n);
        if (!player_exists(player) || (player->field_2C != 1))
            continue;
        heartng = get_player_soul_container(n);
        if (thing_exists(heartng) && (heartng->active_state != 3))
        {
            TRACE_THING(heartng);
            if (creature_can_navigate_to(creatng, &heartng->mappos, NavRtF_Default)) {
                change_creature_owner(creatng, n);
                anger_set_creature_anger_all_types(creatng, 0);
            }
        }
    }
    return false;
}
Esempio n. 5
0
long computer_check_for_accelerate(struct Computer2 *comp, struct ComputerCheck * check)
{
    static RoomKind workers_in_rooms[] = {RoK_LIBRARY,RoK_LIBRARY,RoK_WORKSHOP,RoK_TRAINING,RoK_SCAVENGER};
    struct Thing *thing;
    long i,n;
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_for_accelerate(comp, check);
    if (computer_able_to_use_magic(comp, PwrK_SPEEDCRTR, 8, 3) != 1)
    {
        return 4;
    }
    n = check->param1 % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]));
    if (n <= 0)
        n = ACTION_RANDOM(sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]));
    for (i=0; i < sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]); i++)
    {
        thing = computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(comp, workers_in_rooms[n]);
        if (!thing_is_invalid(thing))
        {
            SYNCDBG(8,"Cast on thing %d",(int)thing->index);
            return 1;
        }
        n = (n+1) % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]));
    }
    return 4;
}
Esempio n. 6
0
long computer_check_for_expand_room(struct Computer2 *comp, struct ComputerCheck * check)
{
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_for_expand_room(comp, check);
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon))
    {
        ERRORLOG("Invalid computer players dungeon");
        return 0;
    }
    long around_start;
    around_start = ACTION_RANDOM(119);
    // Don't work when placing rooms; we could place in an area for room by mistake
    if (is_task_in_progress(comp, CTT_PlaceRoom) || is_task_in_progress(comp, CTT_CheckRoomDug)) {
        SYNCDBG(8,"No rooms expansion - colliding task already in progress");
        return 0;
    }
    if (4 * dungeon->creatures_total_pay / 3 >= dungeon->total_money_owned) {
        SYNCDBG(8,"No rooms expansion - we don't even have money for payday");
        return 0;
    }
    const struct ExpandRooms *expndroom;
    for (expndroom = &expand_rooms[0]; expndroom->rkind != RoK_NONE; expndroom++)
    {
        if (computer_check_for_expand_room_kind(comp, check, expndroom->rkind, expndroom->max_slabs, around_start)) {
            return 1;
        }
    }
    SYNCDBG(8,"No rooms found for expansion");
    return 0;
}
Esempio n. 7
0
void set_thing_draw(struct Thing *thing, long anim, long speed, long scale, char a5, char start_frame, unsigned char draw_class)
{
    unsigned long i;
    thing->anim_sprite = convert_td_iso(anim);
    thing->field_50 &= 0x03;
    thing->field_50 |= (draw_class << 2);
    thing->field_49 = keepersprite_frames(thing->anim_sprite);
    if (speed != -1) {
        thing->field_3E = speed;
    }
    if (scale != -1) {
        thing->sprite_size = scale;
    }
    if (a5 != -1) {
        set_flag_byte(&thing->field_4F, TF4F_Unknown40, a5);
    }
    if (start_frame == -2)
    {
        i = keepersprite_frames(thing->anim_sprite) - 1;
        thing->field_48 = i;
        thing->field_40 = i << 8;
    } else if (start_frame == -1)
    {
        i = ACTION_RANDOM(thing->field_49);
        thing->field_48 = i;
        thing->field_40 = i << 8;
    } else
    {
        i = start_frame;
        thing->field_48 = i;
        thing->field_40 = i << 8;
    }
}
Esempio n. 8
0
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);
    }
}
Esempio n. 9
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;
}
Esempio n. 10
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. 11
0
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;
}
Esempio n. 12
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;
}
Esempio n. 13
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);
    }
}
Esempio n. 14
0
void update_player_sounds(void)
{
    int k;
    struct PlayerInfo *player;
    SYNCDBG(7,"Starting");
    if ((game.operation_flags & GOF_Paused) == 0)
    {
        player = get_my_player();
        process_messages();
        if (!SoundDisabled)
        {
            if (game.audiotrack > 0)
            {
                PlayMusicPlayer(game.audiotrack);
            }
            update_3d_sound_receiver(player);
        }
        game.play_gameturn++;
    }
    find_nearest_rooms_for_ambient_sound();
    process_3d_sounds();
    k = (game.bonus_time-game.play_gameturn) / 2;
    if (bonus_timer_enabled())
    {
      if ((game.bonus_time == game.play_gameturn) ||
         ((game.bonus_time > game.play_gameturn) && (((k <= 100) && ((k % 10) == 0)) ||
          ((k<=300) && ((k % 50) == 0)) || ((k % 250) == 0))) )
        play_non_3d_sample(89);
    }
    // Rare message easter egg
    if ((game.play_gameturn != 0) && ((game.play_gameturn % 20000) == 0))
    {
        if (ACTION_RANDOM(2000) == 0)
        {
          k = UNSYNC_RANDOM(10);
          SYNCDBG(9,"Rare message condition met, selected %d",(int)k);
          if (k == 7)
          {
            output_message(SMsg_PantsTooTight, 0, true);
          } else
          {
            output_message(SMsg_FunnyMessages+k, 0, true);
          }
        }
    }
    SYNCDBG(9,"Finished");
}
Esempio n. 15
0
/**
 * Setups a wanderer creature to move to a random thing in given list.
 * @param first_thing_idx
 * @param wanderer
 * @return
 */
TbBool setup_wanderer_move_to_random_creature_from_list(long first_thing_idx, struct Thing *wanderer)
{
    long possible_targets,target_match;
    possible_targets = get_wanderer_possible_targets_count_in_list(first_thing_idx,wanderer);
    // Select random target
    if (possible_targets < 1) {
        SYNCDBG(4,"The %s cannot wander to creature, there are no targets",thing_model_name(wanderer));
        return false;
    }
    target_match = ACTION_RANDOM(possible_targets);
    if ( wander_to_specific_possible_target_in_list(first_thing_idx, wanderer, target_match) )
    {
        return true;
    }
    WARNLOG("The %s index %d cannot wander to creature, it seem all %d creatures were not navigable",
        thing_model_name(wanderer),(int)wanderer->index,(int)possible_targets);
    return false;
}
Esempio n. 16
0
void setup_workshop_search_for_post(struct Thing *creatng)
{
    struct Room *room;
    struct Thing *postng;
    postng = INVALID_THING;
    room = get_room_thing_is_on(creatng);
    // Find a random slab in the room to be used as our starting point
    long i;
    unsigned long n;
    i = ACTION_RANDOM(room->slabs_count);
    n = room->slabs_list;
    while (i > 0)
    {
        n = get_next_slab_number_in_room(n);
        i--;
    }
    i = room->slabs_count;
    while (i > 0)
    {
        // Loop the slabs list
        if (n <= 0) {
            n = room->slabs_list;
        }
        MapSlabCoord slb_x, slb_y;
        slb_x = subtile_slab_fast(stl_num_decode_x(n));
        slb_y = subtile_slab_fast(stl_num_decode_y(n));
        struct Thing *objtng;
        objtng = get_workshop_equipment_to_work_with_on_subtile(creatng->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y));
        if (!thing_is_invalid(objtng)) {
            postng = objtng;
        }
        n = get_next_slab_number_in_room(n);
        i--;
    }
    if (thing_is_invalid(postng))
    {
        SYNCDBG(9,"Work in %s, the %s moves to new pos",room_code_name(room->kind),thing_model_name(creatng));
        setup_move_to_new_workshop_position(creatng, room, 1);
    } else
    {
        SYNCDBG(9,"Work in %s, the %s found a post",room_code_name(room->kind),thing_model_name(creatng));
        setup_workshop_move(creatng, get_subtile_number(postng->mappos.x.stl.num, postng->mappos.y.stl.num));
    }
}
Esempio n. 17
0
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;
}
Esempio n. 18
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;
}
Esempio n. 19
0
void lightning_modify_palette(struct Thing *thing)
{
    struct PlayerInfo *myplyr;
    // _DK_lightning_modify_palette(thing);
    myplyr = get_my_player();

    if (thing->health == 0)
    {
      PaletteSetPlayerPalette(myplyr, engine_palette);
      myplyr->field_3 &= ~0x08;
      return;
    }
    if (myplyr->acamera == NULL)
    {
        ERRORLOG("No active camera");
        return;
    }
    if (((thing->health % 8) != 7) && (thing->health != 1) && (ACTION_RANDOM(4) != 0))
    {
        if ((myplyr->field_3 & 0x08) != 0)
        {
            if (get_2d_box_distance(&myplyr->acamera->mappos, &thing->mappos) < 11520)
            {
                PaletteSetPlayerPalette(myplyr, engine_palette);
                myplyr->field_3 &= ~0x08;
            }
        }
        return;
    }
    if ((myplyr->view_mode != PVM_ParchFadeIn) && (myplyr->view_mode != PVM_ParchFadeOut) && (myplyr->view_mode != PVM_ParchmentView))
    {
        if ((myplyr->field_3 & 0x08) == 0)
        {
            if (get_2d_box_distance(&myplyr->acamera->mappos, &thing->mappos) < 11520)
            {
              PaletteSetPlayerPalette(myplyr, lightning_palette);
              myplyr->field_3 |= 0x08;
            }
        }
    }
}
Esempio n. 20
0
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;

}
Esempio n. 21
0
struct Room *get_opponent_room(struct Computer2 *comp, PlayerNumber plyr_idx)
{
    static const RoomKind opponent_room_kinds[] = {RoK_DUNGHEART, RoK_PRISON, RoK_LIBRARY, RoK_TREASURE};
    struct Dungeon *dungeon;
    struct Room *room;
    dungeon = get_players_num_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon) || (slab_conf.room_types_count < 1)) {
        return INVALID_ROOM;
    }
    int i,n;
    n = opponent_room_kinds[ACTION_RANDOM(sizeof(opponent_room_kinds)/sizeof(opponent_room_kinds[0]))];
    for (i=0; i < slab_conf.room_types_count; i++)
    {
        room = room_get(dungeon->room_kind[n]);
        if (room_exists(room)) {
            return room;
        }
        n = (n + 1) % slab_conf.room_types_count;
    }
    return INVALID_ROOM;
}
Esempio n. 22
0
long computer_check_for_expand_room(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
		return 4;

    SYNCDBG(8,"Starting");
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) {
        SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner);
        return CTaskRet_Unk4;
    }
    long around_start;
    around_start = ACTION_RANDOM(119);
    // Don't work when placing rooms; we could place in an area for room by mistake
    if (is_task_in_progress(comp, CTT_PlaceRoom) || is_task_in_progress(comp, CTT_CheckRoomDug)) {
        SYNCDBG(8,"No rooms expansion - colliding task already in progress");
        return CTaskRet_Unk0;
    }
    if (computer_player_in_emergency_state(comp)) {
        SYNCDBG(8,"No rooms expansion - emergency state");
        return CTaskRet_Unk0;
    }
    if (get_computer_money_less_cost(comp) < dungeon->creatures_total_pay / 3) {
        SYNCDBG(8,"No rooms expansion - not enough money buffer");
        return CTaskRet_Unk0;
    }
    const struct ExpandRooms *expndroom;
    for (expndroom = &expand_rooms[0]; expndroom->rkind != RoK_NONE; expndroom++)
    {
        if (computer_check_for_expand_room_kind(comp, check, expndroom->rkind, expndroom->max_slabs, around_start)) {
            return CTaskRet_Unk1;
        }
    }
    SYNCDBG(8,"No rooms found for expansion");
    return CTaskRet_Unk0;
}
Esempio n. 23
0
TbBool attempt_anger_job_persuade(struct Thing *creatng)
{
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    if (cctrl->explevel <= 5) {
        return false;
    }
    if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreaturePersuade)) {
        return false;
    }
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(creatng->owner);
    int persuade_count;
    persuade_count = min(dungeon->num_active_creatrs-1, 5);
    if (persuade_count <= 0) {
        return false;
    }
    persuade_count = ACTION_RANDOM(persuade_count) + 1;
    if (!external_set_thing_state(creatng, CrSt_CreaturePersuade)) {
        return false;
    }
    cctrl->byte_9A = persuade_count;
    return true;
}
Esempio n. 24
0
/**
 * Quick attack is just putting CTA spell on enemy room.

 * @param comp
 * @param check
 */
long computer_check_for_quick_attack(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_for_quick_attack(comp, check);
    dungeon = comp->dungeon;
    int creatrs_num;
    creatrs_num = check->param1 * dungeon->num_active_creatrs / 100;
    if (check->param3 >= creatrs_num) {
        return 4;
    }
    if (computer_able_to_use_magic(comp, PwrK_CALL2ARMS, 1, 3) != 1) {
        return 4;
    }
    if ((check_call_to_arms(comp) != 1) || is_there_an_attack_task(comp)) {
        return 4;
    }
    struct Room *room;
    room = get_hated_room_for_quick_attack(comp, check->param3);
    if (room_is_invalid(room)) {
        return 4;
    }
    struct Coord3d pos;
    // TODO COMPUTER_PLAYER We should make sure the place of cast is accessible for creatures
    pos.x.val = subtile_coord_center(room->central_stl_x);
    pos.y.val = subtile_coord_center(room->central_stl_y);
    pos.z.val = subtile_coord(1,0);
    if (check->param3 >= count_creatures_availiable_for_fight(comp, &pos)) {
        return 4;
    }
    if (!create_task_magic_support_call_to_arms(comp, &pos, check->param2, 0, creatrs_num)) {
        return 4;
    }
    output_message(SMsg_EnemyHarassments+ACTION_RANDOM(8), 500, 1);
    return 1;
}
Esempio n. 25
0
TbBool steal_hero(struct PlayerInfo *player, struct Coord3d *pos)
{
    //TODO CONFIG creature models dependency; put them in config files
    static ThingModel skip_steal_models[] = {6, 7};
    static ThingModel prefer_steal_models[] = {3, 12};
    struct Thing *herotng;
    herotng = INVALID_THING;
    int heronum;
    struct Dungeon *herodngn;
    struct CreatureControl *cctrl;
    unsigned long k;
    int i;
    SYNCDBG(8,"Starting");
    herodngn = get_players_num_dungeon(game.hero_player_num);
    k = 0;
    if (herodngn->num_active_creatrs > 0) {
        heronum = ACTION_RANDOM(herodngn->num_active_creatrs);
        i = herodngn->creatr_list_start;
        SYNCDBG(4,"Selecting random creature %d out of %d heroes",(int)heronum,(int)herodngn->num_active_creatrs);
    } else {
        heronum = 0;
        i = 0;
        SYNCDBG(4,"No heroes on map, skipping selection");
    }
    while (i != 0)
    {
        struct Thing *thing;
        thing = thing_get(i);
        TRACE_THING(thing);
        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
        TbBool heroallow;
        heroallow = true;
        ThingModel skipidx;
        for (skipidx=0; skipidx < sizeof(skip_steal_models)/sizeof(skip_steal_models[0]); skipidx++)
        {
            if (thing->model == skip_steal_models[skipidx]) {
                heroallow = false;
            }
        }
        if (heroallow) {
            herotng = thing;
        }
        // If we've reached requested hero number, return either current hero on previously selected one
        if ((heronum <= 0) && thing_is_creature(herotng)) {
            break;
        }
        heronum--;
        if (i == 0) {
            i = herodngn->creatr_list_start;
        }
        // Thing list loop body ends
        k++;
        if (k > CREATURES_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping creatures list");
            erstat_inc(ESE_InfChainTngPerOwner);
            break;
        }
    }
    if (!thing_is_invalid(herotng))
    {
        move_thing_in_map(herotng, pos);
        change_creature_owner(herotng, player->id_number);
        SYNCDBG(3,"Converted %s to owner %d",thing_model_name(herotng),(int)player->id_number);
    }
    else
    {
        i = ACTION_RANDOM(sizeof(prefer_steal_models)/sizeof(prefer_steal_models[0]));
        struct Thing *creatng;
        creatng = create_creature(pos, prefer_steal_models[i], player->id_number);
        if (thing_is_invalid(creatng))
            return false;
        SYNCDBG(3,"Created %s owner %d",thing_model_name(creatng),(int)player->id_number);
    }
    return true;
}
Esempio n. 26
0
TbBool find_place_to_put_door_around_room(const struct Room *room, struct Coord3d *pos)
{
    long m,n;
    m = ACTION_RANDOM(SMALL_AROUND_SLAB_LENGTH);
    for (n = 0; n < SMALL_AROUND_SLAB_LENGTH; n++)
    {
        // Get position containing room center
        MapSlabCoord slb_x,slb_y;
        slb_x = subtile_slab_fast(room->central_stl_x);
        slb_y = subtile_slab_fast(room->central_stl_y);
        // Move the position to edge of the room
        struct Room *sibroom;
        sibroom = slab_room_get(slb_x, slb_y);
        while (!room_is_invalid(sibroom) && (sibroom->index == room->index))
        {
            slb_x += small_around[m].delta_x;
            slb_y += small_around[m].delta_y;
            sibroom = slab_room_get(slb_x, slb_y);
        }
        // Move the position a few tiles further in that direction searching for a place to put door
        //TODO COMPUTER_PLAYER Why we can only have doors if corridor is at center of the room? This should be fixed to allow doors everywhere around room.
        int i;
        for (i = 4; i > 0; i--)
        {
            struct SlabMap *slb;
            slb = get_slabmap_block(slb_x, slb_y);
            if ((slabmap_owner(slb) != room->owner) || (slb->kind != SlbT_CLAIMED)) {
                i = 0;
                break;
            }
            if (tag_cursor_blocks_place_door(room->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y))) {
                break;
            }
            if (!subtile_has_door_thing_on(slab_subtile_center(slb_x), slab_subtile_center(slb_y))) {
                // No door - the position looks ok
                break;
            }
            slb_x += small_around[m].delta_x;
            slb_y += small_around[m].delta_y;
        }
        // Now if we were able to move, then the position seem ok. One last check - make sure the corridor is not dead end and doesn't already have a door
        if (i > 0)
        {
            MapSlabCoord nxslb_x,nxslb_y;
            nxslb_x = slb_x + small_around[m].delta_x;
            nxslb_y = slb_y + small_around[m].delta_y;
            struct SlabMap *nxslb;
            nxslb = get_slabmap_block(nxslb_x, nxslb_y);
            if ((slabmap_owner(nxslb) == room->owner) && (nxslb->kind == SlbT_CLAIMED))
            {
                if (!subtile_has_door_thing_on(slab_subtile_center(nxslb_x), slab_subtile_center(nxslb_y))) {
                    pos->x.val = subtile_coord_center(slab_subtile_center(slb_x));
                    pos->y.val = subtile_coord_center(slab_subtile_center(slb_y));
                    pos->z.val = subtile_coord(1,0);
                    return true;
                }
            }
        }
        m = (m + 1) % SMALL_AROUND_SLAB_LENGTH;
    }
    return false;
}
Esempio n. 27
0
TbBool good_creature_setup_task_in_dungeon(struct Thing *creatng, PlayerNumber target_plyr_idx)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    cctrl = creature_control_get_from_thing(creatng);
    SYNCDBG(8,"The %s performing task %d",thing_model_name(creatng), (int)cctrl->party_objective);
    switch (cctrl->party_objective)
    {
    case CHeroTsk_AttackRooms:
        if (good_setup_attack_rooms(creatng, target_plyr_idx)) {
            return true;
        }
        WARNLOG("Can't attack player %d rooms, switching to attack heart", (int)target_plyr_idx);
        cctrl->party_objective = CHeroTsk_AttackDnHeart;
        return false;
    case CHeroTsk_AttackDnHeart:
        if (good_setup_wander_to_dungeon_heart(creatng, target_plyr_idx)) {
            return true;
        }
        ERRORLOG("Cannot wander to player %d heart", (int)target_plyr_idx);
        return false;
    case CHeroTsk_StealGold:
        crstat = creature_stats_get_from_thing(creatng);
        if (creatng->creature.gold_carried < crstat->gold_hold)
        {
            if (good_setup_loot_treasure_room(creatng, target_plyr_idx)) {
                return true;
            }
            WARNLOG("Can't loot player %d treasury, switching to attack heart", (int)target_plyr_idx);
            cctrl->party_objective = CHeroTsk_AttackDnHeart;
        } else
        {
            if (good_setup_wander_to_exit(creatng)) {
                return true;
            }
            WARNLOG("Can't wander to exit after looting player %d treasury, switching to attack heart", (int)target_plyr_idx);
            cctrl->party_objective = CHeroTsk_AttackDnHeart;
        }
        return false;
    case CHeroTsk_StealSpells:
        if (!creature_is_dragging_spellbook(creatng))
        {
            if (good_setup_loot_research_room(creatng, target_plyr_idx)) {
                return true;
            }
            WARNLOG("Can't loot player %d spells, switching to attack heart", (int)target_plyr_idx);
            cctrl->party_objective = CHeroTsk_AttackDnHeart;
        } else
        {
            if (good_setup_wander_to_exit(creatng)) {
                return true;
            }
            WARNLOG("Can't wander to exit after looting player %d spells, switching to attack heart", (int)target_plyr_idx);
            cctrl->party_objective = CHeroTsk_AttackDnHeart;
        }
        return false;
    case CHeroTsk_AttackEnemies:
        // Randomly select if we will first try to wander to creature, or to special digger
        if (ACTION_RANDOM(2) == 1)
        {
            // Try wander to creature
            if (good_setup_wander_to_creature(creatng, cctrl->party.target_plyr_idx))
            {
                SYNCDBG(17,"Finished - wandering to player %d creature", (int)cctrl->party.target_plyr_idx);
                return true;
            }
            // If the wander failed, try wander to special digger
            if (good_setup_wander_to_spdigger(creatng, cctrl->party.target_plyr_idx))
            {
                SYNCDBG(17,"Finished - wandering to player %d worker", (int)cctrl->party.target_plyr_idx);
                return true;
            }
        } else
        {
            // Try wander to special digger
            if (good_setup_wander_to_spdigger(creatng, cctrl->party.target_plyr_idx))
            {
                SYNCDBG(17,"Finished - wandering to player %d worker", (int)cctrl->party.target_plyr_idx);
                return true;
            }
            // If the wander failed, try wander to creature
            if (good_setup_wander_to_creature(creatng, cctrl->party.target_plyr_idx))
            {
                SYNCDBG(17,"Finished - wandering to player %d creature", (int)cctrl->party.target_plyr_idx);
                return true;
            }
        }
        WARNLOG("Can't attack player %d creature, switching to attack heart", (int)cctrl->party.target_plyr_idx);
        cctrl->party_objective = CHeroTsk_AttackDnHeart;
        return false;
    case CHeroTsk_Default:
    default:
        SYNCDBG(4,"Wrong task, switching to attack enemies");
        cctrl->party_objective = CHeroTsk_AttackEnemies;
        return false;
    }
}
Esempio n. 28
0
short researching(struct Thing *thing)
{
    struct Dungeon *dungeon;
    long i;
    TRACE_THING(thing);
    dungeon = get_dungeon(thing->owner);
    if (is_neutral_thing(thing))
    {
        ERRORLOG("Neutral %s index %d cannot do research",thing_model_name(thing),(int)thing->index);
        remove_creature_from_work_room(thing);
        set_start_state(thing);
        return CrStRet_Unchanged;
    }
    if (!creature_can_do_research(thing))
    {
        if (!is_neutral_thing(thing) && (dungeon->current_research_idx < 0))
        {
            if (is_my_player_number(dungeon->owner))
                output_message(SMsg_NoMoreReseach, 500, true);
        }
        remove_creature_from_work_room(thing);
        set_start_state(thing);
        return CrStRet_Unchanged;
    }
    // Get and verify working room
    struct Room *room;
    room = get_room_thing_is_on(thing);
    if (creature_work_in_room_no_longer_possible(room, RoK_LIBRARY, thing))
    {
        remove_creature_from_work_room(thing);
        set_start_state(thing);
        return CrStRet_ResetFail;
    }

    if (room->used_capacity > room->total_capacity)
    {
        output_message_room_related_from_computer_or_player_action(room->owner, room->kind, OMsg_RoomTooSmall);
        remove_creature_from_work_room(thing);
        set_start_state(thing);
        return CrStRet_ResetOk;
    }
    process_research_function(thing);
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(thing);
    if ( (game.play_gameturn - dungeon->field_AE5 < 50)
      && ((game.play_gameturn + thing->index) & 0x03) == 0)
    {
        external_set_thing_state(thing, CrSt_CreatureBeHappy);
        cctrl->countdown_282 = 50;
        cctrl->long_9A = 0;
        return CrStRet_Modified;
    }
    if (cctrl->instance_id != CrInst_NULL)
      return 1;
    cctrl->field_82++;
    // Shall we do some "Standing and thinking"
    if (cctrl->field_82 <= 128)
    {
      if (cctrl->byte_9A == 3)
      {
          // Do some random thinking
          if ((cctrl->field_82 % 16) == 0)
          {
              i = ACTION_RANDOM(LbFPMath_PI) - LbFPMath_PI/2;
              cctrl->long_9B = ((long)thing->move_angle_xy + i) & LbFPMath_AngleMask;
              cctrl->byte_9A = 4;
          }
      } else
      {
          // Look at different direction while thinking
          if (creature_turn_to_face_angle(thing, cctrl->long_9B) < LbFPMath_PI/18)
          {
              cctrl->byte_9A = 3;
          }
      }
      return 1;
    }
    // Finished "Standing and thinking" - make "new idea" effect and go to next position
    if (!setup_random_head_for_room(thing, room, NavRtF_Default))
    {
        ERRORLOG("Cannot move %s index %d in %s room", thing_model_name(thing),(int)thing->index,room_code_name(room->kind));
        set_start_state(thing);
        return 1;
    }
    thing->continue_state = CrSt_Researching;
    cctrl->field_82 = 0;
    cctrl->byte_9A = 3;
    if (cctrl->explevel < 3)
    {
        create_effect(&thing->mappos, TngEff_Unknown54, thing->owner);
    } else
    if (cctrl->explevel < 6)
    {
        create_effect(&thing->mappos, TngEff_Unknown55, thing->owner);
    } else
    {
        create_effect(&thing->mappos, TngEff_Unknown56, thing->owner);
    }
    return 1;
}
Esempio n. 29
0
short creature_being_scavenged(struct Thing *creatng)
{
    //return _DK_creature_being_scavenged(creatng);
    struct Thing *fellowtng;
    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    //return _DK_make_all_players_creatures_angry(plyr_idx);
    dungeon = get_players_num_dungeon(creatng->owner);
    fellowtng = INVALID_THING;
    if (dungeon->num_active_creatrs <= 1)
    {
        SYNCDBG(19,"No other creatures");
        return 0;
    }
    int n;
    n = ACTION_RANDOM(dungeon->num_active_creatrs-1);
    unsigned long k;
    int i;
    k = 0;
    i = dungeon->creatr_list_start;
    while (i != 0)
    {
        struct Thing *thing;
        thing = thing_get(i);
        TRACE_THING(thing);
        struct CreatureControl *cctrl;
        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
        if ((n <= 0) && (thing->index != creatng->index)) {
            fellowtng = thing;
            break;
        }
        n--;
        // Thing list loop body ends
        k++;
        if (k > CREATURES_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping creatures list");
            break;
        }
    }
    if (thing_is_invalid(fellowtng))
    {
        SYNCDBG(19,"Cannot get creature");
        return 0;
    }
    if (setup_person_move_to_coord(creatng, &fellowtng->mappos, NavRtF_Default) <= 0)
    {
        SYNCDBG(19,"Cannot move to coord");
        return 0;
    }
    creatng->continue_state = CrSt_CreatureBeingScavenged;
    if (!S3DEmitterIsPlayingSample(creatng->snd_emitter_id, 156, 0))
        thing_play_sample(creatng, 156, NORMAL_PITCH, 0, 3, 1, 2, FULL_LOUDNESS);
    SYNCDBG(19,"Finished");
    return 1;
}
Esempio n. 30
0
/**
 *  Finds a random training post near to the current position of given creature.
 *  Used when finding a training post seems to be taking too long; in that case, creature should start training with a nearest post.
 *  Note that this routine does not always select the nearest post - it is enough if it's 3 subtiles away.
 *
 * @param creatng The creature who wish to train with training post.
 */
void setup_training_search_for_post(struct Thing *creatng)
{
    struct Room *room;
    struct Thing *traintng;
    struct Thing *thing;
    long start_slab;
    long min_distance,dist;
    long slb_x,slb_y;
    long i,k;
    room = get_room_thing_is_on(creatng);
    // Let's start from a random slab
    slb_x = -1;
    slb_y = -1;
    min_distance = LONG_MAX;
    traintng = INVALID_THING;
    start_slab = ACTION_RANDOM(room->slabs_count);
    k = start_slab;
    i = room->slabs_list;
    while (i != 0)
    {
        slb_x = slb_num_decode_x(i);
        slb_y = slb_num_decode_y(i);
        i = get_next_slab_number_in_room(i);
        if (k <= 0)
            break;
        k--;
    }
    // Got random starting slab, now sweep room slabs from it
    thing = INVALID_THING;
    k = room->slabs_count;
    i = get_slab_number(slb_x,slb_y);
    while (k > 0)
    {
        slb_x = slb_num_decode_x(i);
        slb_y = slb_num_decode_y(i);
        i = get_next_slab_number_in_room(i);
        if (i == 0)
          i = room->slabs_list;
        // Per room tile code - find a nearest training post
        thing = get_object_at_subtile_of_model_and_owned_by(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 31, creatng->owner);
        if (!thing_is_invalid(thing))
        {
            dist = get_2d_distance(&creatng->mappos, &thing->mappos);
            if (dist < min_distance) {
                traintng = thing;
                min_distance = dist;
                if (min_distance < (3<<8))
                    break;
            }
        }
        // Per room tile code ends
        k--;
    }
    // Got trainer (or not...), now do the correct action
    if (thing_is_invalid(traintng))
    {
        SYNCDBG(6,"Room no longer have training post, moving somewhere else.");
        setup_move_to_new_training_position(creatng, room, true);
    } else
    {
        i = get_subtile_number(traintng->mappos.x.stl.num,traintng->mappos.y.stl.num);
        setup_training_move_near(creatng, i);
    }
}