long instf_attack_room_slab(struct Thing *creatng, long *param) { TRACE_THING(creatng); //return _DK_instf_attack_room_slab(creatng, param); struct Room *room; room = get_room_thing_is_on(creatng); if (room_is_invalid(room)) { ERRORLOG("The %s is not on room",thing_model_name(creatng)); return 0; } struct SlabMap *slb; slb = get_slabmap_thing_is_on(creatng); if (slb->health > 2) { //TODO CONFIG damage made to room slabs is constant - doesn't look good slb->health -= 2; thing_play_sample(creatng, 128 + UNSYNC_RANDOM(3), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return 1; } if (room->owner != game.neutral_player_num) { struct Dungeon *dungeon; dungeon = get_dungeon(room->owner); dungeon->rooms_destroyed++; } if (!delete_room_slab(coord_slab(creatng->mappos.x.val), coord_slab(creatng->mappos.y.val), 1)) { ERRORLOG("Cannot delete %s room tile destroyed by %s",room_code_name(room->kind),thing_model_name(creatng)); return 0; } create_effect(&creatng->mappos, 3, creatng->owner); thing_play_sample(creatng, 47, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return 1; }
void activate_trap_shot_head_for_target90(struct Thing *traptng, struct Thing *creatng) { struct TrapStats *trapstat; trapstat = &trap_stats[traptng->model]; if (trapstat->field_1A <= 0) { ERRORLOG("Trap activation of bad shot kind %d",(int)trapstat->field_1A); return; } struct Thing *shotng; shotng = create_shot(&traptng->mappos, trapstat->field_1A, traptng->owner); if (!thing_is_invalid(shotng)) { { MapCoord crpos_x, crpos_y; MapCoord trpos_x, trpos_y; trpos_x = traptng->mappos.x.val; trpos_y = traptng->mappos.y.val; crpos_x = creatng->mappos.x.val; crpos_y = creatng->mappos.y.val; if (abs(trpos_x - crpos_x) <= abs(trpos_y - crpos_y)) { if (crpos_y >= trpos_y) shotng->move_angle_xy = LbFPMath_PI; else shotng->move_angle_xy = 0; } else { if (crpos_x >= trpos_x) shotng->move_angle_xy = LbFPMath_PI/2; else shotng->move_angle_xy = 3*LbFPMath_PI/2; } } shotng->move_angle_z = 0; struct ShotConfigStats *shotst; shotst = get_shot_model_stats(trapstat->field_1A); struct ComponentVector cvect; angles_to_vector(shotng->move_angle_xy, 0, shotst->old->speed, &cvect); shotng->veloc_push_add.x.val += cvect.x; shotng->veloc_push_add.y.val += cvect.y; shotng->veloc_push_add.z.val += cvect.z; shotng->state_flags |= TF1_PushAdd; shotng->byte_16 = trapstat->field_1B; if (shotst->old->firing_sound > 0) { thing_play_sample(traptng, shotst->old->firing_sound+UNSYNC_RANDOM(shotst->old->firing_sound_variants), NORMAL_PITCH, 0, 3, 0, 6, FULL_LOUDNESS); } if (shotst->old->shot_sound > 0) { thing_play_sample(shotng, shotst->old->shot_sound, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); } } }
void activate_trap(struct Thing *traptng, struct Thing *creatng) { const struct TrapStats *trapstat; traptng->trap.byte_18t = 1; trapstat = &trap_stats[traptng->model]; //TODO CONFIG trap model dependency, make config option instead if (traptng->model == 2) { event_create_event(traptng->mappos.x.val, traptng->mappos.y.val, EvKind_AlarmTriggered, traptng->owner, 0); } thing_play_sample(traptng, 176, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); switch (trapstat->activation_type) { case 1: activate_trap_shot_head_for_target90(traptng, creatng); break; case 2: activate_trap_effect_on_trap(traptng, creatng); break; case 3: activate_trap_shot_on_trap(traptng, creatng); break; case 4: activate_trap_slab_change(traptng, creatng); break; default: ERRORLOG("Illegal trap activation type %d",(int)trapstat->activation_type); break; } }
long instf_damage_wall(struct Thing *creatng, long *param) { SYNCDBG(16,"Starting"); TRACE_THING(creatng); //return _DK_instf_damage_wall(creatng, param); MapSubtlCoord stl_x, stl_y; { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); stl_x = stl_num_decode_x(cctrl->field_284); stl_y = stl_num_decode_y(cctrl->field_284); } struct SlabMap *slb; slb = get_slabmap_for_subtile(stl_x, stl_y); if (slb->health > 2) { slb->health -= 2; } else { place_slab_type_on_map(2, stl_x, stl_y, creatng->owner, 0); do_slab_efficiency_alteration(subtile_slab_fast(stl_x), subtile_slab_fast(stl_y)); } thing_play_sample(creatng, 63+UNSYNC_RANDOM(6), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return 1; }
long instf_reinforce(struct Thing *creatng, long *param) { struct CreatureControl *cctrl; SYNCDBG(16,"Starting"); TRACE_THING(creatng); //return _DK_instf_reinforce(creatng, param); cctrl = creature_control_get_from_thing(creatng); MapSubtlCoord stl_x,stl_y; MapSlabCoord slb_x,slb_y; stl_x = stl_num_decode_x(cctrl->digger.working_stl); stl_y = stl_num_decode_y(cctrl->digger.working_stl); slb_x = subtile_slab_fast(stl_x); slb_y = subtile_slab_fast(stl_y); if (check_place_to_reinforce(creatng, slb_x, slb_y) <= 0) { return 0; } if (cctrl->digger.byte_93 <= 25) { cctrl->digger.byte_93++; if (!S3DEmitterIsPlayingSample(creatng->snd_emitter_id, 172, 0)) { thing_play_sample(creatng, 172, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); } return 0; } cctrl->digger.byte_93 = 0; place_and_process_pretty_wall_slab(creatng, slb_x, slb_y); struct Coord3d pos; pos.x.stl.pos = 128; pos.y.stl.pos = 128; pos.z.stl.pos = 128; long n; for (n=0; n < SMALL_AROUND_LENGTH; n++) { pos.x.stl.num = stl_x + 2 * small_around[n].delta_x; pos.y.stl.num = stl_y + 2 * small_around[n].delta_y; struct Map *mapblk; mapblk = get_map_block_at(pos.x.stl.num, pos.y.stl.num); if (map_block_revealed(mapblk, creatng->owner) && ((mapblk->flags & MapFlg_IsTall) == 0)) { pos.z.val = get_floor_height_at(&pos); create_effect(&pos, imp_spangle_effects[creatng->owner], creatng->owner); } } thing_play_sample(creatng, 41, NORMAL_PITCH, 0, 3, 0, 3, FULL_LOUDNESS); return 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; }
long instf_destroy(struct Thing *creatng, long *param) { struct Dungeon *dungeon; struct Room *room; struct SlabMap *slb; MapSlabCoord slb_x,slb_y; long prev_owner; TRACE_THING(creatng); slb_x = subtile_slab_fast(creatng->mappos.x.stl.num); slb_y = subtile_slab_fast(creatng->mappos.y.stl.num); dungeon = get_dungeon(creatng->owner); slb = get_slabmap_block(slb_x, slb_y); room = room_get(slb->room_index); prev_owner = slabmap_owner(slb); if ( !room_is_invalid(room) && (prev_owner != creatng->owner) ) { if (room->health > 1) { room->health--; return 0; } clear_dig_on_room_slabs(room, creatng->owner); if (room->owner == game.neutral_player_num) { claim_room(room, creatng); } else { MapCoord ccor_x,ccor_y; ccor_x = subtile_coord_center(room->central_stl_x); ccor_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ccor_x, ccor_y, EvKind_RoomLost, room->owner, 0); claim_enemy_room(room, creatng); } thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); create_effects_on_room_slabs(room, imp_spangle_effects[creatng->owner], 0, creatng->owner); return 0; } if (slb->health > 1) { slb->health--; return 0; } if (prev_owner != game.neutral_player_num) { struct Dungeon *prev_dungeon; prev_dungeon = get_dungeon(prev_owner); prev_dungeon->lvstats.territory_lost++; } decrease_dungeon_area(prev_owner, 1); neutralise_enemy_block(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng->owner); remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL); switch_owned_objects_on_destoyed_slab_to_neutral(slb_x, slb_y, prev_owner); dungeon->lvstats.territory_destroyed++; return 1; }
long instf_fart(struct Thing *creatng, long *param) { TRACE_THING(creatng); //return _DK_instf_fart(creatng, param); struct Thing *efftng; efftng = create_effect(&creatng->mappos, 13, creatng->owner); if (!thing_is_invalid(efftng)) efftng->byte_16 = 4; thing_play_sample(creatng,94+UNSYNC_RANDOM(6), NORMAL_PITCH, 0, 3, 0, 4, FULL_LOUDNESS); return 1; }
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; } } }
void play_creature_sound(struct Thing *thing, long snd_idx, long a3, long a4) { struct CreatureSound *crsound; long i; SYNCDBG(8,"Starting"); if (playing_creature_sound(thing, snd_idx)) { return; } crsound = get_creature_sound(thing, snd_idx); if (crsound->index <= 0) { SYNCDBG(19,"No sample %d for creature %d",snd_idx,thing->model); return; } i = UNSYNC_RANDOM(crsound->count); SYNCDBG(18,"Playing sample %d (index %d) for creature %d",snd_idx,crsound->index+i,thing->model); if ( a4 ) { thing_play_sample(thing, crsound->index+i, NORMAL_PITCH, 0, 3, 8, a3, FULL_LOUDNESS); } else { thing_play_sample(thing, crsound->index+i, NORMAL_PITCH, 0, 3, 0, a3, FULL_LOUDNESS); } }
void play_creature_sound_and_create_sound_thing(struct Thing *thing, long snd_idx, long a2) { struct CreatureSound *crsound; struct Thing *efftng; long i; if (playing_creature_sound(thing, snd_idx)) { return; } crsound = get_creature_sound(thing, snd_idx); if (crsound->index <= 0) { SYNCDBG(14,"No sample %d for creature %d",snd_idx,thing->model); return; } i = UNSYNC_RANDOM(crsound->count); efftng = create_effect(&thing->mappos, TngEff_Unknown49, thing->owner); if (!thing_is_invalid(efftng)) { thing_play_sample(efftng, crsound->index+i, NORMAL_PITCH, 0, 3, 0, a2, FULL_LOUDNESS); } }
long instf_pretty_path(struct Thing *creatng, long *param) { struct Dungeon *dungeon; TRACE_THING(creatng); SYNCDBG(16,"Starting"); dungeon = get_dungeon(creatng->owner); MapSlabCoord slb_x,slb_y; slb_x = subtile_slab_fast(creatng->mappos.x.stl.num); slb_y = subtile_slab_fast(creatng->mappos.y.stl.num); create_effect(&creatng->mappos, imp_spangle_effects[creatng->owner], creatng->owner); thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); place_slab_type_on_map(SlbT_CLAIMED, slab_subtile_center(slb_x), slab_subtile_center(slb_y), creatng->owner, 1); do_unprettying(creatng->owner, slb_x, slb_y); do_slab_efficiency_alteration(slb_x, slb_y); increase_dungeon_area(creatng->owner, 1); dungeon->lvstats.area_claimed++; remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL); return 1; }
long instf_tunnel(struct Thing *creatng, long *param) { struct CreatureControl *cctrl; struct SlabMap *slb; SYNCDBG(16,"Starting"); TRACE_THING(creatng); cctrl = creature_control_get_from_thing(creatng); MapSubtlCoord stl_x,stl_y; stl_x = stl_num_decode_x(cctrl->navi.field_15); stl_y = stl_num_decode_y(cctrl->navi.field_15); slb = get_slabmap_for_subtile(stl_x, stl_y); if (slabmap_block_invalid(slb)) { return 0; } thing_play_sample(creatng, 69+UNSYNC_RANDOM(3), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); if (slb->health > 1) { slb->health--; } else { dig_out_block(stl_x, stl_y, creatng->owner); } return 1; }
void play_thing_walking(struct Thing *thing) { struct PlayerInfo *myplyr; myplyr = get_my_player(); struct Camera *cam; cam = myplyr->acamera; { // Skip the thing if its distance to camera is too big MapSubtlDelta dist_x, dist_y; dist_x = coord_subtile(abs(cam->mappos.x.val - (MapCoordDelta)thing->mappos.x.val)); dist_y = coord_subtile(abs(cam->mappos.y.val - (MapCoordDelta)thing->mappos.y.val)); if (dist_x <= dist_y) dist_x = dist_y; if (dist_x >= 10) { return; } } if ((get_creature_model_flags(thing) & CMF_IsSpectator) != 0) { // Spectators don't do sounds return; } long loudness; loudness = (myplyr->view_mode == PVM_CreatureView) ? (FULL_LOUDNESS) : (FULL_LOUDNESS/5); // Flying diptera has a buzzing noise sound if ((get_creature_model_flags(thing) & CMF_IsDiptera) && ((thing->movement_flags & TMvF_Flying) != 0) && (thing->field_60 < (int)thing->mappos.z.val)) { if ( !S3DEmitterIsPlayingSample(thing->snd_emitter_id, 25, 0) ) { thing_play_sample(thing, 25, 100, -1, 2, 0, 2, loudness); } } else { if ( S3DEmitterIsPlayingSample(thing->snd_emitter_id, 25, 0) ) { S3DDeleteSampleFromEmitter(thing->snd_emitter_id, 25, 0); } struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if ((cctrl->field_9) && get_foot_creature_has_down(thing)) { int smpl_variant; smpl_variant = foot_down_sound_sample_variant[4 * ((cctrl->mood_flags & 0x1C) >> 2) + (cctrl->field_67 & 0x1F)]; long smpl_idx; if ((thing->movement_flags & TMvF_Unknown80) != 0) { smpl_idx = 181 + smpl_variant; } else { struct CreatureSound *crsound; crsound = get_creature_sound(thing, CrSnd_Foot); smpl_idx = crsound->index + smpl_variant; } cctrl->field_67 = (cctrl->field_67 ^ (cctrl->field_67 ^ (cctrl->field_67 + 1))) & 0x1F; if ((cctrl->field_67 & 0x1F) >= 4) { cctrl->mood_flags &= ~0x1C; cctrl->mood_flags |= (UNSYNC_RANDOM(4) << 2); cctrl->field_67 &= ~0x1F; } int v15; unsigned short smpl_delay; //TODO CONFIG creature model dependency; remove, add config file option for this v15 = thing->model; if ( v15 == 19 || v15 == 24 ) {//FLY or BUG smpl_delay = 400; } else if ( v15 == 27 ) {//HELL_HOUND smpl_delay = 300; } else { smpl_delay = 100; } thing_play_sample(thing, smpl_idx, smpl_delay, 0, 3, 3, 1, loudness); if ((thing->movement_flags & TMvF_IsOnWater) != 0) { thing_play_sample(thing, 21+SOUND_RANDOM(4), 90+SOUND_RANDOM(20), 0, 3, 3, 1, FULL_LOUDNESS); } } }
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; }
long instf_dig(struct Thing *creatng, long *param) { struct CreatureControl *cctrl; struct Dungeon *dungeon; struct SlabMap *slb; long stl_x,stl_y; long task_idx,taskkind; long dig_damage,gold; SYNCDBG(16,"Starting"); TRACE_THING(creatng); //return _DK_instf_dig(thing, param); cctrl = creature_control_get_from_thing(creatng); dungeon = get_dungeon(creatng->owner); task_idx = cctrl->word_91; { struct MapTask *task; task = get_dungeon_task_list_entry(dungeon,task_idx); taskkind = task->kind; if (task->coords != cctrl->word_8F) { return 0; } stl_x = stl_num_decode_x(cctrl->word_8F); stl_y = stl_num_decode_y(cctrl->word_8F); } slb = get_slabmap_for_subtile(stl_x, stl_y); if (slabmap_block_invalid(slb)) { return 0; } dig_damage = calculate_damage_did_to_slab_with_single_hit(creatng, slb); if (slb->health > dig_damage) { if (!slab_kind_is_indestructible(slb->kind)) slb->health -= dig_damage; thing_play_sample(creatng, 63 + UNSYNC_RANDOM(6), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); create_effect(&creatng->mappos, TngEff_Unknown25, creatng->owner); if (taskkind == SDDigTask_MineGold) { gold = calculate_gold_digged_out_of_slab_with_single_hit(dig_damage, creatng->owner, cctrl->explevel, slb); creatng->creature.gold_carried += gold; dungeon->lvstats.gold_mined += gold; } return 0; } // slb->health <= dig_damage - we're going to destroy the slab remove_from_task_list(creatng->owner, task_idx); if (taskkind == SDDigTask_MineGold) { gold = calculate_gold_digged_out_of_slab_with_single_hit(slb->health, creatng->owner, cctrl->explevel, slb); creatng->creature.gold_carried += gold; dungeon->lvstats.gold_mined += gold; mine_out_block(stl_x, stl_y, creatng->owner); if (dig_has_revealed_area(stl_x, stl_y, creatng->owner)) { EventIndex evidx; evidx = event_create_event_or_update_nearby_existing_event( subtile_coord_center(stl_x), subtile_coord_center(stl_y), EvKind_AreaDiscovered, creatng->owner, 0); if ((evidx > 0) && is_my_player_number(creatng->owner)) output_message(SMsg_DugIntoNewArea, 0, true); } } else if (taskkind == SDDigTask_DigEarth) { dig_out_block(stl_x, stl_y, creatng->owner); if (dig_has_revealed_area(stl_x, stl_y, creatng->owner)) { EventIndex evidx; evidx = event_create_event_or_update_nearby_existing_event( subtile_coord_center(stl_x), subtile_coord_center(stl_y), EvKind_AreaDiscovered, creatng->owner, 0); if ((evidx > 0) && is_my_player_number(creatng->owner)) output_message(SMsg_DugIntoNewArea, 0, true); } } check_map_explored(creatng, stl_x, stl_y); thing_play_sample(creatng, 72 + UNSYNC_RANDOM(3), NORMAL_PITCH, 0, 3, 0, 4, FULL_LOUDNESS); return 1; }
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; }