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

[ Xedra Evolved ] Species based snares [Robot, Cyborg, Nether, Changeling] #73867

Merged
merged 21 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions data/json/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,15 @@
],
"flags": [ "EFFECT_LIMB_SCORE_MOD" ]
},
{
"type": "effect_type",
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
"id": "immobilization",
"name": [ "Immobilized" ],
"desc": [ "You can't move!" ],
"rating": "bad",
"show_in_info": true,
"flags": [ "EFFECT_IMPEDING" ]
},
{
"type": "effect_type",
"id": "stunned",
Expand Down
11 changes: 11 additions & 0 deletions data/json/traps.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,17 @@
"difficulty": 0,
"action": "snare_light"
},
{
"type": "trap",
"id": "tr_species_snare",
"name": "species snare trap",
"color": "red",
"symbol": "~",
"visibility": 1,
"avoidance": 8,
"difficulty": 0,
"action": "snare_species"
},
{
"type": "trap",
"id": "tr_beartrap",
Expand Down
50 changes: 50 additions & 0 deletions data/mods/Xedra_Evolved/items/inventor/traps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[
{
"id": "stunning_qr_trap",
"type": "TOOL",
"name": "stunning qr trap",
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
"category": "traps",
"properties": { "capture_species": "ROBOT" },
"description": "A jagged and eldritch looking QR code ready to be placed wherever you are concerned about mechanical eyes. Will trap robots if they wander into it.",
"weight": "1 g",
"volume": "5 ml",
"longest_side": "5 cm",
"price": "250 USD",
"price_postapoc": "5 USD",
"material": "plastic",
"symbol": "*",
"color": "light_gray",
"flags": [ "SINGLE_USE" ],
"use_action": {
"type": "place_trap",
"trap": "tr_species_snare",
"moves": 150,
"practice": 2,
"done_message": "You set the qr code."
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
}
},
{
"id": "stunning_arg_trap",
"type": "TOOL",
"name": "stunning arg trap",
"category": "traps",
"properties": { "capture_species": "CYBORG" },
"description": "A jagged and eldritch looking QR code ready to be placed wherever you are concerned about mechanical eyes. Will trap cyborgs if they wander into it.",
"weight": "1 g",
"volume": "5 ml",
"longest_side": "5 cm",
"price": "250 USD",
"price_postapoc": "5 USD",
"material": "plastic",
"symbol": "*",
"color": "light_gray",
"flags": [ "SINGLE_USE" ],
"use_action": {
"type": "place_trap",
"trap": "tr_species_snare",
"moves": 150,
"practice": 2,
"done_message": "You set the qr code."
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
}
}
]
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions src/iuse_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3925,6 +3925,10 @@ std::optional<int> place_trap_actor::use( Character *p, item &it, const tripoint
p->mod_moves( -move_cost_final );

place_and_add_as_known( *p, pos, data.trap );
const trap &placed_trap = here.tr_at( pos );
if( !placed_trap.is_null() ) {
const_cast<trap &>( placed_trap ).set_trap_data( it.typeId() );
}
for( const tripoint &t : here.points_in_radius( pos, data.trap.obj().get_trap_radius(), 0 ) ) {
if( t != pos ) {
place_and_add_as_known( *p, t, outer_layer_trap );
Expand Down
5 changes: 5 additions & 0 deletions src/monmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static const efftype_id effect_dragging( "dragging" );
static const efftype_id effect_grabbed( "grabbed" );
static const efftype_id effect_harnessed( "harnessed" );
static const efftype_id effect_led_by_leash( "led_by_leash" );
static const efftype_id effect_immobilization( "immobilization" );
RenechCDDA marked this conversation as resolved.
Show resolved Hide resolved
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
static const efftype_id effect_no_sight( "no_sight" );
static const efftype_id effect_operating( "operating" );
static const efftype_id effect_pacified( "pacified" );
Expand Down Expand Up @@ -969,6 +970,10 @@ void monster::move()
moves = 0;
return;
}
if( has_effect( effect_immobilization ) ) {
moves = 0;
return;
}
if( has_effect( effect_stunned ) || has_effect( effect_psi_stunned ) ) {
stumble();
moves = 0;
Expand Down
9 changes: 7 additions & 2 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4790,8 +4790,10 @@ void submap::store( JsonOut &jsout ) const
jsout.start_array();
jsout.write( p.x );
jsout.write( p.y );
const trap_id &trap_at = get_trap( p );
// TODO: jsout should support writing an id like jsout.write( trap_id )
jsout.write( get_trap( p ).id().str() );
jsout.write( trap_at.id().str() );
jsout.write( trap_at->trap_item_type );
jsout.end_array();
}
}
Expand Down Expand Up @@ -5048,7 +5050,10 @@ void submap::load( const JsonValue &jv, const std::string &member_name, int vers
// TODO: jsin should support returning an id like jsin.get_id<trap>()
const trap_str_id trid( trap_entry.next_string() );
m->trp[p.x][p.y] = trid.id();
if( trap_entry.size() > 3 ) {
if( trap_entry.has_more() ) {
const_cast<trap &>( m->trp[p.x][p.y].obj() ).set_trap_data( itype_id( trap_entry.next_string() ) );
}
if( trap_entry.size() > 4 ) {
trap_entry.throw_error( "Too many values for trap entry" );
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/trap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,11 @@ bool trap::easy_take_down() const
return avoidance == 0 && difficulty == 0;
}

void trap::set_trap_data( itype_id trap_item_type_id )
{
trap_item_type = trap_item_type_id;
}

bool trap::can_not_be_disarmed() const
{
return difficulty >= 99;
Expand Down
4 changes: 4 additions & 0 deletions src/trap.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ bool cot( const tripoint &p, Creature *c, item *i );
bool beartrap( const tripoint &p, Creature *c, item *i );
bool snare_light( const tripoint &p, Creature *c, item *i );
bool snare_heavy( const tripoint &p, Creature *c, item *i );
bool snare_species( const tripoint &p, Creature *critter, item *trap_item );
bool board( const tripoint &p, Creature *c, item *i );
bool caltrops( const tripoint &p, Creature *c, item *i );
bool caltrops_glass( const tripoint &p, Creature *c, item *i );
Expand Down Expand Up @@ -160,6 +161,7 @@ struct trap {
// For disassembly?
std::vector<std::tuple<itype_id, int, int>> components;
public:
std::optional<itype_id> trap_item_type;
// data required for trapfunc::spell()
fake_spell spell_data;
int comfort = 0;
Expand Down Expand Up @@ -229,6 +231,8 @@ struct trap {

bool is_trivial_to_spot() const;

void set_trap_data( itype_id trap_item_type_id );

Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
/**
* Some traps are part of the terrain (e.g. pits) and can therefore not be disarmed
* via the usual mechanics. They can be "disarmed" by changing the terrain they are part of.
Expand Down
63 changes: 63 additions & 0 deletions src/trapfunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ static const damage_type_id damage_pure( "pure" );
static const efftype_id effect_beartrap( "beartrap" );
static const efftype_id effect_heavysnare( "heavysnare" );
static const efftype_id effect_in_pit( "in_pit" );
static const efftype_id effect_immobilization( "immobilization" );
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
static const efftype_id effect_lightsnare( "lightsnare" );
static const efftype_id effect_ridden( "ridden" );
static const efftype_id effect_slimed( "slimed" );
Expand Down Expand Up @@ -682,6 +683,67 @@ bool trapfunc::snare_heavy( const tripoint &p, Creature *c, item * )
return true;
}

bool trapfunc::snare_species( const tripoint &p, Creature *critter, item * )
{
map &here = get_map();
const trap &laid_trap = here.tr_at( p );
if( !critter ) { // Nothing to capture
return false;
}

if( laid_trap.is_null() ) {
return false; //Should never happen but just in case
}

if( !laid_trap.trap_item_type.has_value() ) {
debugmsg( "Active trap %s has no stored item to determine species value. Removing trap to avoid crashing.",
laid_trap.name() );
here.remove_trap( p );
return false;
}

item trap_item = item( item::find_type( laid_trap.trap_item_type.value() ) );

if( !trap_item.has_property( "capture_species" ) ) {
debugmsg( "placed trap's item type %s has no \"capture_species\" property!" );
here.remove_trap( p );
return false;
}

const std::string spec = trap_item.get_property_string( "capture_species" );
const species_id species_to_capture = species_id( spec );

if( !critter->in_species( species_to_capture ) ) {
critter->add_msg_if_player( m_good, _( "You harmlessly pass a %1$s." ),
laid_trap.name() );
return false;
}

{
sounds::sound( p, 8, sounds::sound_t::combat, _( "phwoom!" ), false, "trap", "species_snare" );
}

if( critter ) {
const bodypart_id hit = critter->get_random_body_part_of_type( body_part_type::type::leg );

critter->add_msg_if_player( m_bad, _( "A %1$s catches your %2$s!" ),
laid_trap.name(), hit->name.translated() );

if( critter->has_effect( effect_ridden ) ) {
add_msg( m_warning, _( "Your %1$s is caught by a %2$s!" ), critter->get_name(), laid_trap.name() );
}
if( !critter->is_avatar() ) {
add_msg_if_player_sees( p, "%1$s is caught by a %2$s!", critter->get_name(), laid_trap.name() );
Maleclypse marked this conversation as resolved.
Show resolved Hide resolved
}
// Actual effects
critter->add_effect( effect_immobilization, 10_turns, hit );
critter->check_dead_state();
}

here.remove_trap( p );
return true;
}

bool trapfunc::landmine( const tripoint &p, Creature *c, item * )
{
// tiny animals are too light to trigger land mines
Expand Down Expand Up @@ -1669,6 +1731,7 @@ const trap_function &trap_function_from_string( const std::string &function_name
{ "blade", trapfunc::blade },
{ "snare_light", trapfunc::snare_light },
{ "snare_heavy", trapfunc::snare_heavy },
{ "snare_species", trapfunc::snare_species },
{ "landmine", trapfunc::landmine },
{ "telepad", trapfunc::telepad },
{ "goo", trapfunc::goo },
Expand Down
Loading