Example #1
0
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;
}
Example #2
0
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);
        }
    }
}
Example #3
0
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;
}
Example #5
0
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;
}
Example #9
0
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;
        }
    }
}
Example #10
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);
    }
}
Example #11
0
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);
    }
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
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;
}
Example #16
0
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;
}