Ejemplo n.º 1
0
void god_lightning_choose_next_creature(struct Thing *shotng)
{
    SYNCDBG(16,"Starting for %s index %d owner %d",thing_model_name(shotng),(int)shotng->index,(int)shotng->owner);
    //_DK_god_lightning_choose_next_creature(shotng); return;
    long best_dist;
    struct Thing *best_thing;
    best_dist = LONG_MAX;
    best_thing = INVALID_THING;

    unsigned long k;
    int i;
    const struct StructureList *slist;
    slist = get_list_for_thing_class(TCls_Creature);
    k = 0;
    i = slist->index;
    while (i != 0)
    {
        struct Thing *thing;
        thing = thing_get(i);
        if (thing_is_invalid(thing))
        {
            ERRORLOG("Jump to invalid thing detected");
            break;
        }
        i = thing->next_of_class;
        // Per-thing code
        //TODO use hit_type instead of hard coded conditions
        if ((shotng->owner != thing->owner) && !thing_is_picked_up(thing)
            && !creature_is_being_unconscious(thing) && !creature_is_dying(thing))
        {
            long dist;
            dist = get_2d_distance(&shotng->mappos, &thing->mappos);
            if (dist < best_dist)
            {
                const struct MagicStats *pwrdynst;
                pwrdynst = get_power_dynamic_stats(PwrK_LIGHTNING);
                int spell_lev;
                spell_lev = shotng->shot.byte_19;
                if (spell_lev > SPELL_MAX_LEVEL)
                    spell_lev = SPELL_MAX_LEVEL;
                if (subtile_coord(pwrdynst->strength[spell_lev],0) > dist)
                {
                    if (line_of_sight_2d(&shotng->mappos, &thing->mappos)) {
                        best_dist = dist;
                        best_thing = thing;
                    }
                }
            }
        }
        // Per-thing code ends
        k++;
        if (k > slist->count)
        {
            ERRORLOG("Infinite loop detected when sweeping things list");
            erstat_inc(ESE_InfChainTngPerClass);
            break;
        }
    }
    SYNCDBG(8,"The best target for %s index %d owner %d is %s index %d owner %d",
        thing_model_name(shotng),(int)shotng->index,(int)shotng->owner,
        thing_model_name(best_thing),(int)best_thing->index,(int)best_thing->owner);
    if (!thing_is_invalid(best_thing)) {
        shotng->shot.target_idx = best_thing->index;
    } else {
        shotng->shot.target_idx = 0;
    }
}
Ejemplo n.º 2
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);
    }
}
Ejemplo n.º 3
0
long creature_tunnel_to(struct Thing *creatng, struct Coord3d *pos, short speed)
{
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    SYNCDBG(6,"Move %s from (%d,%d) to (%d,%d) with speed %d",thing_model_name(creatng),(int)creatng->mappos.x.stl.num,(int)creatng->mappos.y.stl.num,(int)pos->x.stl.num,(int)pos->y.stl.num,(int)speed);
    //return _DK_creature_tunnel_to(creatng, pos, a3);
    long i;
    cctrl->navi.field_19[0] = 0;
    if (get_2d_box_distance(&creatng->mappos, pos) <= 32)
    {
        // We've reached the destination
        creature_set_speed(creatng, 0);
        return 1;
    }
    i = cctrl->party.long_8B;
    if ((i > 0) && (i < LONG_MAX))
    {
        cctrl->party.long_8B++;
    }
    if ((pos->x.val != cctrl->navi.pos_final.x.val)
     || (pos->y.val != cctrl->navi.pos_final.y.val)
     || (pos->z.val != cctrl->navi.pos_final.z.val))
    {
        pos->z.val = get_thing_height_at(creatng, pos);
        initialise_wallhugging_path_from_to(&cctrl->navi, &creatng->mappos, pos);
    }
    long tnlret;
    tnlret = get_next_position_and_angle_required_to_tunnel_creature_to(creatng, pos, cctrl->party.byte_8F);
    if (tnlret == 2)
    {
        i = cctrl->navi.field_15;
        if (cctrl->navi.field_17 != i)
        {
            cctrl->navi.field_17 = i;
        } else
        if (cctrl->instance_id == CrInst_NULL)
        {
            set_creature_instance(creatng, CrInst_TUNNEL, 0, 0, 0);
        }
    }
    MapCoordDelta dist;
    dist = get_2d_distance(&creatng->mappos, &cctrl->navi.pos_next);
    if (dist <= 16)
    {
        creature_turn_to_face_angle(creatng, cctrl->navi.field_D);
        creature_set_speed(creatng, 0);
        return 0;
    }
    if (dist > 768)
    {
        ERRORLOG("Move %s index %d to (%d,%d) reset - wallhug distance %d too large",thing_model_name(creatng),(int)creatng->index,(int)pos->x.stl.num,(int)pos->y.stl.num,(int)dist);
        clear_wallhugging_path(&cctrl->navi);
        creature_set_speed(creatng, speed);
        return 0;
    }
    if (creature_turn_to_face(creatng, &cctrl->navi.pos_next))
    {
        creature_set_speed(creatng, 0);
        return 0;
    }
    cctrl->moveaccel.x.val = cctrl->navi.pos_next.x.val - (MapCoordDelta)creatng->mappos.x.val;
    cctrl->moveaccel.y.val = cctrl->navi.pos_next.y.val - (MapCoordDelta)creatng->mappos.y.val;
    cctrl->moveaccel.z.val = 0;
    cctrl->flgfield_2 |= 0x01;
    creature_set_speed(creatng, min(speed,dist));
    return 0;
}