Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Traps: InstantPlacement & RemoveOnceDepleted #3635

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions config/fxdata/trapdoor.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ TriggerAlarm = 0
PlaceOnBridge = 0
; If set to 1 allows the trap to be placed anywhere on a slab. This results in up to 9 traps per tile.
PlaceOnSubtile = 0
; Place the trap immediately without needing imps to drag the crate to arm it.
InstantPlacement = 0
; Destroy the trap once it runs out of Shots.
RemoveOnceDepleted = 0
; Amount of hit points the trap have.
Health = 0
; Can the trap be destroyed by attacking it. If 1 it can by any attack, 0 only by units with 'DISARM ability', -1 by nobody.
Expand Down
140 changes: 88 additions & 52 deletions src/config_trapdoor.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,58 +63,60 @@ const struct NamedCommand trapdoor_door_commands[] = {
};

const struct NamedCommand trapdoor_trap_commands[] = {
{"NAME", 1},
{"MANUFACTURELEVEL", 2},
{"MANUFACTUREREQUIRED", 3},
{"SHOTS", 4},
{"TIMEBETWEENSHOTS", 5},
{"SELLINGVALUE", 6},
{"NAMETEXTID", 7},
{"TOOLTIPTEXTID", 8},
{"CRATE", 9},
{"SYMBOLSPRITES", 10},
{"POINTERSPRITES", 11},
{"PANELTABINDEX", 12},
{"TRIGGERTYPE", 13},
{"ACTIVATIONTYPE", 14},
{"EFFECTTYPE", 15},
{"ANIMATIONID", 16},
{"MODEL", 16},//backward compatibility
{"MODELSIZE", 17},
{"ANIMATIONSPEED", 18},
{"UNANIMATED", 19},
{"HIDDEN", 20},
{"SLAPPABLE", 21},
{"TRIGGERALARM", 22},
{"HEALTH", 23},
{"UNSHADED", 24},
{"RANDOMSTARTFRAME", 25},
{"THINGSIZE", 26},
{"HITTYPE", 27},
{"LIGHTRADIUS", 28},
{"LIGHTINTENSITY", 29},
{"LIGHTFLAGS", 30},
{"TRANSPARENCYFLAGS", 31},
{"SHOTVECTOR", 32},
{"DESTRUCTIBLE", 33},
{"UNSTABLE", 34},
{"UNSELLABLE", 35},
{"PLACEONBRIDGE", 36},
{"SHOTORIGIN", 37},
{"PLACESOUND", 38},
{"TRIGGERSOUND", 39},
{"RECHARGEANIMATIONID", 40},
{"ATTACKANIMATIONID", 41},
{"DESTROYEDEFFECT", 42},
{"INITIALDELAY", 43},
{"PLACEONSUBTILE", 44},
{"FLAMEANIMATIONID", 45},
{"FLAMEANIMATIONSPEED", 46},
{"FLAMEANIMATIONSIZE", 47},
{"FLAMEANIMATIONOFFSET", 48},
{"FLAMETRANSPARENCYFLAGS", 49},
{"DETECTINVISIBLE", 50},
{NULL, 0},
{"NAME", 1},
{"MANUFACTURELEVEL", 2},
{"MANUFACTUREREQUIRED", 3},
{"SHOTS", 4},
{"TIMEBETWEENSHOTS", 5},
{"SELLINGVALUE", 6},
{"NAMETEXTID", 7},
{"TOOLTIPTEXTID", 8},
{"CRATE", 9},
{"SYMBOLSPRITES", 10},
{"POINTERSPRITES", 11},
{"PANELTABINDEX", 12},
{"TRIGGERTYPE", 13},
{"ACTIVATIONTYPE", 14},
{"EFFECTTYPE", 15},
{"ANIMATIONID", 16},
{"MODEL", 16}, // Backward compatibility.
{"MODELSIZE", 17},
{"ANIMATIONSPEED", 18},
{"UNANIMATED", 19},
{"HIDDEN", 20},
{"SLAPPABLE", 21},
{"TRIGGERALARM", 22},
{"HEALTH", 23},
{"UNSHADED", 24},
{"RANDOMSTARTFRAME", 25},
{"THINGSIZE", 26},
{"HITTYPE", 27},
{"LIGHTRADIUS", 28},
{"LIGHTINTENSITY", 29},
{"LIGHTFLAGS", 30},
{"TRANSPARENCYFLAGS", 31},
{"SHOTVECTOR", 32},
{"DESTRUCTIBLE", 33},
{"UNSTABLE", 34},
{"UNSELLABLE", 35},
{"PLACEONBRIDGE", 36},
{"SHOTORIGIN", 37},
{"PLACESOUND", 38},
{"TRIGGERSOUND", 39},
{"RECHARGEANIMATIONID", 40},
{"ATTACKANIMATIONID", 41},
{"DESTROYEDEFFECT", 42},
{"INITIALDELAY", 43},
{"PLACEONSUBTILE", 44},
{"FLAMEANIMATIONID", 45},
{"FLAMEANIMATIONSPEED", 46},
{"FLAMEANIMATIONSIZE", 47},
{"FLAMEANIMATIONOFFSET", 48},
{"FLAMETRANSPARENCYFLAGS", 49},
{"DETECTINVISIBLE", 50},
{"INSTANTPLACEMENT", 51},
{"REMOVEONCEDEPLETED", 52},
{NULL, 0},
};

const struct NamedCommand door_properties_commands[] = {
Expand Down Expand Up @@ -207,6 +209,8 @@ TbBool parse_trapdoor_trap_blocks(char *buf, long len, const char *config_textna
trapst->notify = false;
trapst->place_on_bridge = false;
trapst->place_on_subtile = false;
trapst->instant_placement = false;
trapst->remove_once_depleted = false;
trapst->health = 1;
trapst->destructible = 0;
trapst->unstable = 0;
Expand Down Expand Up @@ -1127,6 +1131,38 @@ TbBool parse_trapdoor_trap_blocks(char *buf, long len, const char *config_textna
COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname);
}
break;
case 51: // INSTANTPLACEMENT
if (get_conf_parameter_single(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
{
k = atoi(word_buf);
if (k >= 0)
{
trapst->instant_placement = k;
n++;
}
}
if (n < 1)
{
CONFWRNLOG("Incorrect value of \"%s\" parameter in [%.*s] block of %s file.",
COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname);
}
break;
case 52: // REMOVEONCEDEPLETED
if (get_conf_parameter_single(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
{
k = atoi(word_buf);
if (k >= 0)
{
trapst->remove_once_depleted = k;
n++;
}
}
if (n < 1)
{
CONFWRNLOG("Incorrect value of \"%s\" parameter in [%.*s] block of %s file.",
COMMAND_TEXT(cmd_num), blocknamelen, blockname, config_textname);
}
break;
case ccr_comment:
break;
case ccr_endOfFile:
Expand Down
2 changes: 2 additions & 0 deletions src/config_trapdoor.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct TrapConfigStats {
TbBool notify;
TbBool place_on_bridge;
TbBool place_on_subtile;
TbBool instant_placement;
TbBool remove_once_depleted;
HitPoints health;
char destructible;
char unstable;
Expand Down
112 changes: 61 additions & 51 deletions src/lvl_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,57 +217,59 @@ const struct NamedCommand creature_select_criteria_desc[] = {
};

const struct NamedCommand trap_config_desc[] = {
{"NameTextID", 1},
{"TooltipTextID", 2},
{"SymbolSprites", 3},
{"PointerSprites", 4},
{"PanelTabIndex", 5},
{"Crate", 6},
{"ManufactureLevel", 7},
{"ManufactureRequired", 8},
{"Shots", 9},
{"TimeBetweenShots", 10},
{"SellingValue", 11},
{"AnimationID", 12},
{"Model", 12}, //legacy name
{"ModelSize", 13},
{"AnimationSpeed", 14},
{"TriggerType", 15},
{"ActivationType", 16},
{"EffectType", 17},
{"Hidden", 18},
{"TriggerAlarm", 19},
{"Slappable", 20},
{"Unanimated", 21},
{"Health", 22},
{"Unshaded", 23},
{"RandomStartFrame", 24},
{"ThingSize", 25},
{"HitType", 26},
{"LightRadius", 27},
{"LightIntensity", 28},
{"LightFlags", 29},
{"TransparencyFlags", 30},
{"ShotVector", 31},
{"Destructible", 32},
{"Unstable", 33},
{"Unsellable", 34},
{"PlaceOnBridge", 35},
{"ShotOrigin", 36},
{"PlaceSound", 37},
{"TriggerSound", 38},
{"RechargeAnimationID", 39},
{"AttackAnimationID", 40},
{"DestroyedEffect", 41},
{"InitialDelay", 42},
{"PlaceOnSubtile", 43},
{"FlameAnimationID", 44},
{"FlameAnimationSpeed", 45},
{"FlameAnimationSize", 46},
{"FlameAnimationOffset", 47},
{"FlameTransparencyFlags", 48},
{"DetectInvisible", 49},
{NULL, 0},
{"NameTextID", 1},
{"TooltipTextID", 2},
{"SymbolSprites", 3},
{"PointerSprites", 4},
{"PanelTabIndex", 5},
{"Crate", 6},
{"ManufactureLevel", 7},
{"ManufactureRequired", 8},
{"Shots", 9},
{"TimeBetweenShots", 10},
{"SellingValue", 11},
{"AnimationID", 12},
{"Model", 12}, // Legacy name.
{"ModelSize", 13},
{"AnimationSpeed", 14},
{"TriggerType", 15},
{"ActivationType", 16},
{"EffectType", 17},
{"Hidden", 18},
{"TriggerAlarm", 19},
{"Slappable", 20},
{"Unanimated", 21},
{"Health", 22},
{"Unshaded", 23},
{"RandomStartFrame", 24},
{"ThingSize", 25},
{"HitType", 26},
{"LightRadius", 27},
{"LightIntensity", 28},
{"LightFlags", 29},
{"TransparencyFlags", 30},
{"ShotVector", 31},
{"Destructible", 32},
{"Unstable", 33},
{"Unsellable", 34},
{"PlaceOnBridge", 35},
{"ShotOrigin", 36},
{"PlaceSound", 37},
{"TriggerSound", 38},
{"RechargeAnimationID", 39},
{"AttackAnimationID", 40},
{"DestroyedEffect", 41},
{"InitialDelay", 42},
{"PlaceOnSubtile", 43},
{"FlameAnimationID", 44},
{"FlameAnimationSpeed", 45},
{"FlameAnimationSize", 46},
{"FlameAnimationOffset", 47},
{"FlameTransparencyFlags", 48},
{"DetectInvisible", 49},
{"InstantPlacement", 50},
{"RemoveOnceDepleted", 51},
{NULL, 0},
};

const struct NamedCommand room_config_desc[] = {
Expand Down Expand Up @@ -1632,6 +1634,8 @@ static void new_trap_type_check(const struct ScriptLine* scline)
trapst->notify = false;
trapst->place_on_bridge = false;
trapst->place_on_subtile = false;
trapst->instant_placement = false;
trapst->remove_once_depleted = false;
trapst->health = 1;
trapst->destructible = 0;
trapst->unstable = 0;
Expand Down Expand Up @@ -1921,6 +1925,12 @@ static void set_trap_configuration_process(struct ScriptContext *context)
case 49: // DetectInvisible
trapst->detect_invisible = value;
break;
case 50: // InstantPlacement
trapst->instant_placement = value;
break;
case 51: // RemoveOnceDepleted
trapst->remove_once_depleted = value;
break;
default:
WARNMSG("Unsupported Trap configuration, variable %d.", context->value->shorts[1]);
break;
Expand Down
29 changes: 19 additions & 10 deletions src/player_instances.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,8 +1226,9 @@ struct Room *player_build_room_at(MapSubtlCoord stl_x, MapSubtlCoord stl_y, Play

TbBool player_place_trap_at(MapSubtlCoord stl_x, MapSubtlCoord stl_y, PlayerNumber plyr_idx, ThingModel tngmodel)
{
if (!is_trap_placeable(plyr_idx, tngmodel)) {
WARNLOG("Player %d tried to build %s but has none to place",(int)plyr_idx,trap_code_name(tngmodel));
if (!is_trap_placeable(plyr_idx, tngmodel))
{
WARNLOG("Player %d tried to build %s but has none to place", (int)plyr_idx, trap_code_name(tngmodel));
return false;
}
struct TrapConfigStats* trap_cfg = get_trap_model_stats(tngmodel);
Expand All @@ -1240,21 +1241,28 @@ TbBool player_place_trap_at(MapSubtlCoord stl_x, MapSubtlCoord stl_y, PlayerNumb
{
set_coords_to_slab_center(&pos, subtile_slab(stl_x), subtile_slab(stl_y));
}
delete_room_slabbed_objects(get_slab_number(subtile_slab(stl_x),subtile_slab(stl_y)));
delete_room_slabbed_objects(get_slab_number(subtile_slab(stl_x), subtile_slab(stl_y)));
struct Thing* traptng = create_trap(&pos, tngmodel, plyr_idx);
if (thing_is_invalid(traptng)) {
if (thing_is_invalid(traptng))
{
return false;
}
traptng->mappos.z.val = get_thing_height_at(traptng, &traptng->mappos);
traptng->trap.revealed = 0;
struct Dungeon* dungeon = get_players_num_dungeon(plyr_idx);

remove_workshop_item_from_amount_placeable(plyr_idx, TCls_Trap, tngmodel);
if (placing_offmap_workshop_item(plyr_idx, TCls_Trap, tngmodel)) {
if (placing_offmap_workshop_item(plyr_idx, TCls_Trap, tngmodel))
{
remove_workshop_item_from_amount_stored(plyr_idx, TCls_Trap, tngmodel, WrkCrtF_NoStored);
rearm_trap(traptng);
dungeon->lvstats.traps_armed++;
}
else if (trap_cfg->instant_placement)
{
remove_workshop_object_from_player(plyr_idx, trap_crate_object_model(tngmodel));
rearm_trap(traptng);
dungeon->lvstats.traps_armed++;
}
dungeon->camera_deviate_jump = 192;
if (is_my_player_number(plyr_idx))
{
Expand All @@ -1265,13 +1273,14 @@ TbBool player_place_trap_at(MapSubtlCoord stl_x, MapSubtlCoord stl_y, PlayerNumb

TbBool player_place_door_at(MapSubtlCoord stl_x, MapSubtlCoord stl_y, PlayerNumber plyr_idx, ThingModel tngmodel)
{
if (!is_door_placeable(plyr_idx, tngmodel)) {
WARNLOG("Player %d tried to build %s but has none to place",(int)plyr_idx,door_code_name(tngmodel));
if (!is_door_placeable(plyr_idx, tngmodel))
{
WARNLOG("Player %d tried to build %s but has none to place", (int)plyr_idx, door_code_name(tngmodel));
return 0;
}
unsigned char orient = find_door_angle(stl_x, stl_y, plyr_idx);
struct Coord3d pos;
set_coords_to_slab_center(&pos,subtile_slab(stl_x),subtile_slab(stl_y));
set_coords_to_slab_center(&pos, subtile_slab(stl_x), subtile_slab(stl_y));
create_door(&pos, tngmodel, orient, plyr_idx, 0);
do_slab_efficiency_alteration(subtile_slab(stl_x), subtile_slab(stl_y));
struct Dungeon* dungeon = get_players_num_dungeon(plyr_idx);
Expand All @@ -1286,7 +1295,7 @@ TbBool player_place_door_at(MapSubtlCoord stl_x, MapSubtlCoord stl_y, PlayerNumb
remove_workshop_object_from_player(plyr_idx, door_crate_object_model(tngmodel));
break;
default:
WARNLOG("Placeable door %s amount for player %d was incorrect; fixed",door_code_name(tngmodel),(int)dungeon->owner);
WARNLOG("Placeable door %s amount for player %d was incorrect; fixed", door_code_name(tngmodel), (int)dungeon->owner);
dungeon->mnfct_info.door_amount_placeable[tngmodel] = 0;
break;
}
Expand Down
Loading