Ejemplo n.º 1
0
TbBool creature_move_to_using_teleport(struct Thing *thing, struct Coord3d *pos, long walk_speed)
{
    struct CreatureControl *cctrl;
    short destination_valid;
    cctrl = creature_control_get_from_thing(thing);
    if (creature_instance_is_available(thing, CrInst_TELEPORT)
     && creature_instance_has_reset(thing, CrInst_TELEPORT)
     && (cctrl->instance_id == CrInst_NULL))
    {
        // Creature can only be teleported to a revealed location
        destination_valid = true;
        if (!is_hero_thing(thing) && !is_neutral_thing(thing)) {
            destination_valid = subtile_revealed(pos->x.stl.num, pos->y.stl.num, thing->owner);
        }
        if (destination_valid)
         {
             // Use teleport only over large enough distances
             if (get_2d_box_distance(&thing->mappos, pos) > COORD_PER_STL*game.min_distance_for_teleport)
             {
                 set_creature_instance(thing, CrInst_TELEPORT, 1, 0, pos);
                 return true;
             }
         }
    }
    return false;
}
Ejemplo n.º 2
0
short good_leave_through_exit_door(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Thing *tmptng;
    // Debug code to find incorrect states
    if (!is_hero_thing(thing))
    {
        ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner);
        set_start_state(thing);
        erstat_inc(ESE_BadCreatrState);
        return false;
    }
    //return _DK_good_leave_through_exit_door(thing);
    tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num);
    if (thing_is_invalid(tmptng))
    {
        return 0;
    }
    cctrl = creature_control_get_from_thing(thing);
    thing->creature.gold_carried = 0;
    cctrl->field_282 = game.hero_door_wait_time;
    cctrl->byte_8A = tmptng->creation_turn;
    place_thing_in_creature_controlled_limbo(thing);
    internal_set_thing_state(thing, CrSt_GoodWaitInExitDoor);
    return 1;
}
Ejemplo n.º 3
0
short good_drops_gold(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);
        erstat_inc(ESE_BadCreatrState);
        return 0;
    }
    //return _DK_good_drops_gold(thing);
    GoldAmount amount;
    amount = game.pot_of_gold_holds;
    if (thing->creature.gold_carried <= game.pot_of_gold_holds)
        amount = thing->creature.gold_carried;
    struct Thing *gldtng;
    gldtng = create_object(&thing->mappos, 6, thing->owner, -1);
    if (thing_is_invalid(gldtng)) {
        return 0;
    }
    gldtng->valuable.gold_stored = amount;
    thing->creature.gold_carried -= amount;
    // Update size of the gold object
    add_gold_to_pile(gldtng, 0);
    internal_set_thing_state(thing, CrSt_GoodBackAtStart);
    return 1;
}
Ejemplo n.º 4
0
TbBool destroy_trap(struct Thing *traptng)
{
    if ((traptng->trap.num_shots == 0) && !is_neutral_thing(traptng) && !is_hero_thing(traptng)) {
        readd_workshop_item_to_amount_placeable(traptng->owner, traptng->class_id, traptng->model);
    }
    delete_thing_structure(traptng, 0);
    return true;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
TngUpdateRet update_trap_trigger(struct Thing *traptng)
{
    if (traptng->trap.num_shots <= 0) {
        return TUFRet_Unchanged;
    }
    TbBool do_trig;
    switch (trap_stats[traptng->model].trigger_type)
    {
    case 1:
        do_trig = update_trap_trigger_line_of_sight_90(traptng);
        break;
    case 2:
        do_trig = update_trap_trigger_pressure(traptng);
        break;
    default:
        ERRORLOG("Illegal trap trigger type %d",(int)trap_stats[traptng->model].trigger_type);
        do_trig = false;
        break;
    }
    if (do_trig)
    {
        const struct ManfctrConfig *mconf;
        mconf = &game.traps_config[traptng->model];
        traptng->trap.long_14t = game.play_gameturn + mconf->shots_delay;
        int n;
        n = traptng->trap.num_shots;
        if ((n > 0) && (n != 255))
        {
            traptng->trap.num_shots = n - 1;
            if (traptng->trap.num_shots == 0)
            {
                // If the trap is in strange location, destroy it after it's depleted
                struct SlabMap *slb;
                slb = get_slabmap_thing_is_on(traptng);
                if ((slb->kind != SlbT_CLAIMED) && (slb->kind != SlbT_PATH)) {
                    traptng->health = -1;
                }
                traptng->field_4F &= 0x10;
                traptng->field_4F |= 0x20;
                if (!is_neutral_thing(traptng) && !is_hero_thing(traptng)) {
                    remove_workshop_item_from_amount_placeable(traptng->owner, traptng->class_id, traptng->model);
                }
            }
        }
        return TUFRet_Modified;
    }
    return TUFRet_Unchanged;
}
Ejemplo n.º 7
0
short good_wait_in_exit_door(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Thing *tmptng;
    // Debug code to find incorrect states
    if (!is_hero_thing(thing))
    {
        ERRORLOG("Non hero thing %s index %d, owner %d - reset",
            thing_model_name(thing), (int)thing->index, (int)thing->owner);
        set_start_state(thing);
        erstat_inc(ESE_BadCreatrState);
        return 0;
    }
    //return _DK_good_wait_in_exit_door(thing);
    cctrl = creature_control_get_from_thing(thing);
    if (cctrl->field_282 <= 0)
        return 0;
    cctrl->field_282--;
    if (cctrl->field_282 == 0)
    {
        tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num);
        if (!thing_is_invalid(tmptng))
        {
            if (cctrl->byte_8A == tmptng->creation_turn)
            {
                remove_thing_from_creature_controlled_limbo(thing);
                set_start_state(thing);
                return 1;
            }
        }
        thing->creature.gold_carried = 0;
        tmptng = thing_get(cctrl->dragtng_idx);
        TRACE_THING(tmptng);
        if (!thing_is_invalid(tmptng))
        {
            delete_thing_structure(tmptng, 0);
        }
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects|CrDed_NotReallyDying);
    }
    return 0;
}
Ejemplo n.º 8
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;

}
Ejemplo n.º 9
0
TbBool thing_is_valid_scavenge_target(const struct Thing *calltng, const struct Thing *scavtng)
{
    if (!thing_is_creature(scavtng) || (scavtng->model != calltng->model)) {
        return false;
    }
    if (!is_neutral_thing(scavtng))
    {
        if (!players_are_enemies(calltng->owner, scavtng->owner)) {
            return false;
        }
    }
    if (thing_is_picked_up(scavtng)) {
        return false;
    }
    if (is_thing_passenger_controlled(scavtng) || creature_is_kept_in_custody(scavtng)) {
        return false;
    }
    if (is_hero_thing(scavtng) && (!gameadd.scavenge_good_allowed)) {
        return false;
    }
    if (is_neutral_thing(scavtng) && (!gameadd.scavenge_neutral_allowed)) {
        return false;
    }
    struct PlayerInfo *scavplyr;
    scavplyr = INVALID_PLAYER;
    if (!is_neutral_thing(scavtng)) {
        scavplyr = get_player(scavtng->owner);
    }
    if (scavplyr->controlled_thing_idx != scavtng->index)
    {
        struct CreatureControl *cctrl;
        cctrl = creature_control_get_from_thing(scavtng);
        if (game.play_gameturn - cctrl->temple_cure_gameturn > game.temple_scavenge_protection_turns)
        {
            return true;
        }
    }
    return false;
}
Ejemplo n.º 10
0
short good_returns_to_start(struct Thing *thing)
{
    struct Thing *heartng;
    // Debug code to find incorrect states
    SYNCDBG(7,"Starting");
    if (!is_hero_thing(thing))
    {
        ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner);
        set_start_state(thing);
        erstat_inc(ESE_BadCreatrState);
        return 0;
    }
    //return _DK_good_returns_to_start(thing);
    heartng = get_player_soul_container(thing->owner);
    TRACE_THING(heartng);
    //TODO CREATURE_AI Heroes don't usually have hearts; maybe they should also go back to hero gates, or any room?
    if (!setup_person_move_to_coord(thing, &heartng->mappos, NavRtF_Default))
    {
        return 0;
    }
    thing->continue_state = CrSt_GoodBackAtStart;
    return 1;
}
Ejemplo n.º 11
0
short good_doing_nothing(struct Thing *creatng)
{
    struct CreatureControl *cctrl;
    struct PlayerInfo *player;
    long nturns;
    PlayerNumber target_plyr_idx;
    //return _DK_good_doing_nothing(creatng);
    SYNCDBG(18,"Starting");
    TRACE_THING(creatng);
    // Debug code to find incorrect states
    if (!is_hero_thing(creatng))
    {
        ERRORLOG("Non hero %s index %d owned by player %d - reset",
            thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        set_start_state(creatng);
        return 0;
    }
    cctrl = creature_control_get_from_thing(creatng);
    if (creature_control_invalid(cctrl))
    {
        ERRORLOG("Invalid creature control; no action");
        return 0;
    }
    // Respect the idle time - just wander around some time
    nturns = game.play_gameturn - cctrl->idle.start_gameturn;
    if (nturns <= 1) {
        return 1;
    }
    // Do some wandering also if can't find any task to do
    if (cctrl->field_5 > (long)game.play_gameturn)
    {
        if (creature_choose_random_destination_on_valid_adjacent_slab(creatng)) {
            creatng->continue_state = CrSt_GoodDoingNothing;
        }
        return 1;
    }
    // Done wandering - find a target player
    target_plyr_idx = cctrl->party.target_plyr_idx;
    if (target_plyr_idx != -1)
    {
        player = get_player(target_plyr_idx);
        if (player_invalid(player))
        {
            ERRORLOG("Invalid target player in %s index %d owned by player %d - reset",
                thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
            cctrl->party.target_plyr_idx = -1;
            return 0;
        }
        if (player->victory_state != VicS_LostLevel)
        {
            nturns = game.play_gameturn - cctrl->long_91;
            if (nturns > 400)
            {
                // Go to the previously chosen dungeon
                if (!creature_can_get_to_dungeon(creatng,target_plyr_idx))
                {
                    // Cannot get to the originally selected dungeon - reset it
                    cctrl->party.target_plyr_idx = -1;
                }
            } else
            if (nturns >= 0)
            {
                // Waiting - move around a bit
                if (creature_choose_random_destination_on_valid_adjacent_slab(creatng))
                {
                    creatng->continue_state = CrSt_GoodDoingNothing;
                    return 0;
                }
            } else
            {
                // Value lower than 0 would mean it is invalid
                WARNLOG("Invalid wait time detected for %s, value %ld",thing_model_name(creatng),(long)cctrl->long_91);
                cctrl->long_91 = 0;
            }
        } else
        {
            // The player we've chosen has lost - we'll have to find other target
            cctrl->party.target_plyr_idx = -1;
        }
    }
    target_plyr_idx = cctrl->party.target_plyr_idx;
    if (target_plyr_idx == -1)
    {
        nturns = game.play_gameturn - cctrl->long_91;
        if (nturns > 400)
        {
            cctrl->long_91 = game.play_gameturn;
            cctrl->byte_8C = 1;
        }
        nturns = game.play_gameturn - cctrl->long_8D;
        if (nturns > 64)
        {
            cctrl->long_8D = game.play_gameturn;
            cctrl->party.target_plyr_idx = good_find_enemy_dungeon(creatng);
        }
        target_plyr_idx = cctrl->party.target_plyr_idx;
        if (target_plyr_idx == -1)
        {
            SYNCDBG(4,"No enemy dungeon to perform %s index %d task",
                thing_model_name(creatng),(int)creatng->index);
            if (creature_choose_random_destination_on_valid_adjacent_slab(creatng))
            {
                creatng->continue_state = CrSt_GoodDoingNothing;
                return 1;
            }
            cctrl->field_5 = game.play_gameturn + 16;
        }
        return 1;
    }
    if (good_creature_setup_task_in_dungeon(creatng, target_plyr_idx)) {
        return 1;
    }
    // If there are problems with the task, do a break before re-trying
    cctrl->field_5 = game.play_gameturn + 200;
    return 0;
}