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; } }
/** * 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); } }
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; }