TbBool move_creature_to_nearest_valid_position(struct Thing *thing) { struct Coord3d pos; pos.x.val = thing->mappos.x.val; pos.y.val = thing->mappos.y.val; pos.z.val = thing->mappos.z.val; if (!get_nearest_valid_position_for_creature_at(thing, &pos)) { return false; } move_thing_in_map(thing, &pos); return true; }
short creature_scavenged_disappear(struct Thing *thing) { struct CreatureControl *cctrl; struct Dungeon *dungeon; struct Room *room; struct Coord3d pos; long stl_x, stl_y; long i; //return _DK_creature_scavenged_disappear(thing); cctrl = creature_control_get_from_thing(thing); cctrl->byte_9A--; if (cctrl->byte_9A > 0) { if ((cctrl->byte_9A == 7) && (cctrl->byte_9B < PLAYERS_COUNT)) { create_effect(&thing->mappos, get_scavenge_effect_element(cctrl->byte_9B), thing->owner); } return 0; } // We don't really have to convert coordinates into numbers and back to XY. i = get_subtile_number(cctrl->scavenge.stl_9D_x, cctrl->scavenge.stl_9D_y); stl_x = stl_num_decode_x(i); stl_y = stl_num_decode_y(i); room = subtile_room_get(stl_x, stl_y); if (room_is_invalid(room) || (room->kind != RoK_SCAVENGER)) { ERRORLOG("Room %s at (%d,%d) disappeared.",room_code_name(RoK_SCAVENGER),(int)stl_x,(int)stl_y); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); return -1; } if (find_random_valid_position_for_thing_in_room(thing, room, &pos)) { move_thing_in_map(thing, &pos); anger_set_creature_anger_all_types(thing, 0); dungeon = get_dungeon(cctrl->byte_9B); dungeon->creatures_scavenge_gain++; if (is_my_player_number(thing->owner)) output_message(SMsg_MinionScanvenged, 0, true); cctrl->byte_9C = thing->owner; change_creature_owner(thing, cctrl->byte_9B); internal_set_thing_state(thing, CrSt_CreatureScavengedReappear); return 0; } else { ERRORLOG("No valid position inside %s room for %s.",room_code_name(room->kind),thing_model_name(thing)); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); return -1; } }
void process_armageddon_influencing_creature(struct Thing *creatng) { if (game.armageddon_cast_turn != 0) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); // If Armageddon is on, teleport creature to its position if ((cctrl->armageddon_teleport_turn != 0) && (cctrl->armageddon_teleport_turn <= game.play_gameturn)) { cctrl->armageddon_teleport_turn = 0; create_effect(&creatng->mappos, imp_spangle_effects[creatng->owner], creatng->owner); move_thing_in_map(creatng, &game.armageddon.mappos); } } }
void set_room_playing_ambient_sound(struct Coord3d *pos, long sample_idx) { struct Thing *thing; long i; //_DK_set_room_playing_ambient_sound(pos, sample_idx);return; if (game.ambient_sound_thing_idx == 0) { ERRORLOG("No room ambient sound object"); return; } thing = thing_get(game.ambient_sound_thing_idx); if ( thing_is_invalid(thing) ) { ERRORLOG("Invalid room ambient sound object"); return; } if (sample_idx != 0) { move_thing_in_map(thing, pos); i = thing->snd_emitter_id; if (i != 0) { if ( !S3DEmitterIsPlayingSample(i, sample_idx, 0) ) { S3DDeleteAllSamplesFromEmitter(thing->snd_emitter_id); thing_play_sample(thing, sample_idx, NORMAL_PITCH, -1, 3, 0, 6, FULL_LOUDNESS); } } else { thing_play_sample(thing, sample_idx, NORMAL_PITCH, -1, 3, 0, 6, FULL_LOUDNESS); } } else { i = thing->snd_emitter_id; if (i != 0) { S3DDestroySoundEmitterAndSamples(i); thing->snd_emitter_id = 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; }
TbBool create_workshop_object_in_workshop_room(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel) { struct Coord3d pos; struct Thing *cratetng; struct Room *room; struct Dungeon *dungeon; SYNCDBG(7,"Making player %d new %s",(int)plyr_idx,thing_class_code_name(tngclass)); pos.x.val = 0; pos.y.val = 0; pos.z.val = 0; switch (tngclass) { case TCls_Trap: cratetng = create_object(&pos, trap_crate_object_model(tngmodel), plyr_idx, -1); break; case TCls_Door: cratetng = create_object(&pos, door_crate_object_model(tngmodel), plyr_idx, -1); break; default: cratetng = INVALID_THING; ERRORLOG("No known workshop crate can represent %s model %d",thing_class_code_name(tngclass),(int)tngmodel); break; } if (thing_is_invalid(cratetng)) { ERRORLOG("Could not create workshop crate thing for %s",thing_class_code_name(tngclass)); return false; } room = find_random_room_for_thing_with_spare_room_item_capacity(cratetng, plyr_idx, RoK_WORKSHOP, 0); if (room_is_invalid(room)) { ERRORLOG("No %s room found which would accept %s crate",room_code_name(RoK_WORKSHOP),thing_class_code_name(tngclass)); destroy_object(cratetng); return false; } if (!find_random_valid_position_for_thing_in_room_avoiding_object(cratetng, room, &pos)) { ERRORLOG("Could not find a place in %s index %d for the new %s crate", room_code_name(room->kind),(int)room->index,thing_class_code_name(tngclass)); destroy_object(cratetng); return false; } pos.z.val = get_thing_height_at(cratetng, &pos); move_thing_in_map(cratetng, &pos); if (!add_workshop_object_to_workshop(room, cratetng)) { ERRORLOG("Could not fit %s crate in %s index %d", thing_class_code_name(tngclass),room_code_name(room->kind),(int)room->index); destroy_object(cratetng); return false; } dungeon = get_players_num_dungeon(plyr_idx); switch (tngclass) { case TCls_Trap: if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Built) == 0) { event_create_event(cratetng->mappos.x.val, cratetng->mappos.y.val, EvKind_NewTrap, plyr_idx, tngmodel); } break; case TCls_Door: if ((dungeon->door_build_flags[tngmodel] & MnfBldF_Built) == 0) { event_create_event(cratetng->mappos.x.val, cratetng->mappos.y.val, EvKind_NewDoor, plyr_idx, tngmodel); } break; default: break; } create_effect(&pos, TngEff_Unknown56, cratetng->owner); thing_play_sample(cratetng, 89, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return true; }