/** * Removes traps on the subtile and all sibling subtiles. * Either treats the action as selling and removes corresponding crate from workshop, * or treats it as destroying and updates workshop counts to skip re-arming the destroyed trap. * * @param stl_x Central subtile X coordinate. * @param stl_y Central subtile Y coordinate. * @param sell_value Value to be added to treasury if selling traps; if not selling but just removing, should be null. * @return Amount of traps removed. */ long remove_traps_around_subtile(MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *sell_value) { long i,k; long total; total = 0; for (k=0; k < AROUND_TILES_COUNT; k++) { struct Thing *traptng; traptng = get_trap_for_position(stl_x+around[k].delta_x, stl_y+around[k].delta_y); if (!thing_is_invalid(traptng)) { if (sell_value != NULL) { // Do the refund only if we were able to sell armed trap i = game.traps_config[traptng->model].selling_value; if (traptng->trap.num_shots == 0) { // Trap not armed - try selling crate from workshop if (remove_workshop_item_from_amount_stored(traptng->owner, traptng->class_id, traptng->model, WrkCrtF_NoOffmap) > WrkCrtS_None) { remove_workshop_object_from_player(traptng->owner, trap_crate_object_model(traptng->model)); (*sell_value) += i; } } else { // Trap armed - we can get refund (*sell_value) += i; } // We don't want to increase trap_amount_placeable, so we'll not use destroy_trap() there delete_thing_structure(traptng, 0); } else { destroy_trap(traptng); } total++; } } return total; }
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; }