Skip to content

Commit

Permalink
[Aftershock] Update and Expand Hacking System (CleverRaven#79496)
Browse files Browse the repository at this point in the history
* Begin Major Rework to Hacking EOC

* Hacks can critically fail

* More work on Hacking Eocs

Remove the debug message,
Hack now uses generic failures unless otherwise specified by the furniture,
Fix accidently rolling a d11 when it should be a d10,
Fix minor failures triggering alongside critical failures

* More types of failures for all other hackables

* Furniture can define a power cost mult

* More hacking system revisions

Filter viable hacking tools based on tool quality and flags,
Remove IDs from the consume power EOCs and instead use flags to determine the behavior,
Change Bionics to use a separate cost formula so the power draw feels more impactful,
Implement supplying a success EOC per furniture to define custom behavior,
Implement Hack no charge flag for items that allow hacking but don't user power,
Wrist computer can now be used for hacking,
Rebalance Esper Summons so hack of 1 is the lowest tool quality

* Hack minor fail chance scales with skill-difficulty delta

* Lint

* Just use a separate equation for bionics entirely. Also make the Infolink a  batter hacking tool

* Minor fail chance scales too, but is always slightly above crit fail chance

* Lint

* Add documentation for the hacking eoc

* Correct incorrect documentation
  • Loading branch information
QuillInkwell authored Feb 6, 2025
1 parent 4fbc240 commit bbc845d
Show file tree
Hide file tree
Showing 9 changed files with 378 additions and 53 deletions.
25 changes: 0 additions & 25 deletions data/mods/Aftershock/EOC/_reusable_conditions.json

This file was deleted.

179 changes: 158 additions & 21 deletions data/mods/Aftershock/EOC/hacking_eoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,51 @@
"num_args": 3,
"return": "_0 - _1 * afs_hack_skill(1) < _2 ? _2 : _0 - _1* afs_hack_skill(1)"
},
{
"type": "jmath_function",
"id": "afs_hack_bonus",
"//": "Intended as: Tool Quality + ( Base Focus Mod * (Focus - Focus Threshold) / Focus Threshold ):rounded to nearest int",
"//1": "Below 100 Focus your focus mod will be negative and you are punished. At 100 focus your mod will be 0. Above 100 focus your mod will be positive and you will be rewarded.",
"//2": "ARGS: (Hack Tool Quality, Current Focus)",
"num_args": 2,
"return": "_0 + trunc( 4 * ( ( _1 - 100 ) / 100 ) )"
},
{
"type": "effect_on_condition",
"id": "EOC_afs_hack_unlock",
"condition": { "and": [ { "expects_vars": [ "furn_pos", "difficulty", "t_radius" ] }, { "u_has_effect": "afs_hack_done" } ] },
"id": "EOC_start_lock_hack",
"condition": { "and": [ { "expects_vars": [ "furn_pos", "t_delay", "difficulty", "t_radius" ] }, "u_can_see" ] },
"effect": [
{ "math": [ "_t_delay = afs_hack_time_adjust(_t_delay, time('20s'), time('2m'))" ] },
{ "math": [ "_hack_cost = (5 * (_t_delay / time('10m') )) * max(1, _power_cost_mult)" ] },
{ "math": [ "_hack_cost_bionic = (energy('2 kJ') * (_t_delay / time('10m') )) * max(1, _power_cost_mult)" ] },
{
"run_eocs": [
"u_run_inv_eocs": "manual",
"title": "Select a Hacking tool",
"search_data": [
{ "condition": { "math": [ "n_quality('HACK') > 0" ] }, "flags": "HACK_NO_CHARGE" },
{
"id": "_EOC_afs_hack_unlock",
"condition": { "roll_contested": { "math": [ "afs_hack_skill(1)" ] }, "die_size": 4, "difficulty": { "context_val": "difficulty" } },
"effect": [
{
"u_transform_radius": { "context_val": "t_radius" },
"ter_furn_transform": "afs_multi_unlock",
"target_var": { "context_val": "furn_pos" }
}
],
"false_effect": { "u_message": "You fail to override the device." }
"condition": { "and": [ { "math": [ "n_quality('HACK') > 0" ] }, { "math": [ "_hack_cost_bionic < u_val('power')" ] } ] },
"flags": "USES_BIONIC_POWER"
},
{
"condition": { "and": [ { "math": [ "n_quality('HACK') > 0" ] }, { "math": [ "_hack_cost < n_val('power')" ] } ] },
"excluded_flags": "USES_BIONIC_POWER",
"uses_energy": true
}
]
],
"true_eocs": [ "EOC_hack_with_tool" ]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_start_lock_hack",
"condition": {
"and": [ { "expects_vars": [ "furn_pos", "t_delay", "difficulty", "t_radius" ] }, { "test_eoc": "EOC_CONDITION_can_hack" } ]
},
"id": "EOC_hack_with_tool",
"effect": [
{ "math": [ "_t_delay = afs_hack_time_adjust(_t_delay, time('20s'), time('2m'))" ] },
{ "npc_set_flag": "ACTIVE_HACK_TOOL" },
{ "u_message": "You connect to the lock controller." },
{ "u_assign_activity": "ACT_afs_hack", "duration": { "context_val": "t_delay" } },
{ "math": [ "u_hack_bonus = afs_hack_bonus( n_quality('HACK'), u_val('focus') )" ] },
{ "run_eocs": [ "EOC_hack_item_power_consume", "EOC_hack_bionic_power_consume" ] },
{
"run_eocs": "EOC_afs_hack_unlock",
"time_in_future": { "context_val": "t_delay" },
Expand All @@ -67,7 +79,132 @@
"t_radius": { "context_val": "t_radius" }
}
}
],
"false_effect": { "u_message": "You need either an electrohack or working computer to attempt a hack.", "popup": true }
]
},
{
"type": "effect_on_condition",
"id": "EOC_hack_item_power_consume",
"effect": [
{
"u_run_inv_eocs": "all",
"search_data": [ { "flags": "ACTIVE_HACK_TOOL", "excluded_flags": "USES_BIONIC_POWER", "uses_energy": true } ],
"true_eocs": [
{
"id": "EOC_hack_item_power_consume_found_item",
"effect": [ { "math": [ "n_val('power') -= _hack_cost" ] }, { "npc_unset_flag": "ACTIVE_HACK_TOOL" } ]
}
]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_hack_bionic_power_consume",
"effect": [
{
"u_run_inv_eocs": "all",
"search_data": [ { "flags": [ "ACTIVE_HACK_TOOL", "USES_BIONIC_POWER" ] } ],
"true_eocs": [
{
"id": "EOC_hack_bionic_power_consume_found_item",
"effect": [ { "math": [ "u_val('power') -= _hack_cost_bionic" ] }, { "npc_unset_flag": "ACTIVE_HACK_TOOL" } ]
}
]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_hack_unlock",
"condition": { "and": [ { "expects_vars": [ "furn_pos", "difficulty", "t_radius" ] }, { "u_has_effect": "afs_hack_done" } ] },
"effect": [
{
"run_eocs": [
{
"id": "EOC_afs_hack_success",
"condition": { "roll_contested": { "math": [ "afs_hack_skill(1)" ] }, "die_size": 4, "difficulty": { "context_val": "difficulty" } },
"effect": [
{
"if": { "compare_string": [ { "u_val": "hack_success_eoc" }, "" ] },
"then": [ { "u_add_var": "hack_success_eoc", "value": "EOC_afs_hack_generic_success" } ]
},
{ "run_eocs": [ { "u_val": "hack_success_eoc" } ] },
{ "u_add_var": "hack_minor_failure_eoc", "value": "" },
{ "u_add_var": "hack_critical_fail_eoc", "value": "" },
{ "u_add_var": "hack_success_eoc", "value": "" }
],
"false_effect": [ { "run_eocs": [ "EOC_afs_hack_failure" ] } ]
}
]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_hack_generic_success",
"effect": [
{
"u_transform_radius": { "context_val": "t_radius" },
"ter_furn_transform": "afs_multi_unlock",
"target_var": { "context_val": "furn_pos" }
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_hack_failure",
"effect": [
{ "u_message": "You fail to override the device.", "type": "bad" },
{ "math": [ "_failure_roll = rand(9)" ] },
{
"if": { "compare_string": [ { "u_val": "hack_minor_failure_eoc" }, "" ] },
"then": [ { "u_add_var": "hack_minor_failure_eoc", "value": "EOC_afs_generic_hack_minor_failures" } ]
},
{
"if": { "compare_string": [ { "u_val": "hack_critical_fail_eoc" }, "" ] },
"then": [ { "u_add_var": "hack_critical_fail_eoc", "value": "EOC_afs_generic_hack_critical_fail" } ]
},
{
"if": { "math": [ "_failure_roll <= clamp(_difficulty - afs_hack_skill(1), 1, 10)" ] },
"then": [ { "run_eocs": [ { "u_val": "hack_critical_fail_eoc" } ] }, { "math": [ "_failure_roll = 10" ] } ]
},
{
"if": { "math": [ "_failure_roll <= clamp(_difficulty - afs_hack_skill(1) + 3, 1, 10)" ] },
"then": [ { "run_eocs": [ { "u_val": "hack_minor_failure_eoc" } ] } ]
},
{ "u_add_var": "hack_minor_failure_eoc", "value": "" },
{ "u_add_var": "hack_critical_fail_eoc", "value": "" },
{ "u_add_var": "hack_success_eoc", "value": "" }
]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_generic_hack_minor_failures",
"effect": [
{
"set_string_var": [ "EOC_afs_generic_hack_minor_failure_alarm", "EOC_afs_generic_hack_minor_failure_hurt" ],
"target_var": { "context_val": "failure_eoc" }
},
{ "run_eocs": [ { "context_val": "failure_eoc" } ] }
]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_generic_hack_critical_fail",
"effect": [ { "u_transform_radius": 0, "ter_furn_transform": "afs_multi_lockdown", "target_var": { "context_val": "furn_pos" } } ]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_generic_hack_minor_failure_alarm",
"effect": [
{ "u_message": "You set off the devices alarm!", "type": "bad" },
{ "custom_light_level": 80, "length": [ "1 seconds", "10 seconds" ] },
{ "u_make_sound": "Alarm Bleeping", "volume": 15, "type": "alarm" }
]
},
{
"type": "effect_on_condition",
"id": "EOC_afs_generic_hack_minor_failure_hurt",
"effect": [ { "u_message": "The device shocks you!", "type": "bad" }, { "u_deal_damage": "electric", "amount": 10 } ]
}
]
68 changes: 68 additions & 0 deletions data/mods/Aftershock/doc/Hacking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Hacking
### Hackable Furniture
To define a Hackable Furniture in Aftershock you need to give it an examine action that triggers an EOC. This EOC must call ```EOC_start_lock_hack``` and must set up several essential variables. Refer to the following chart below for what variables are available to you and which ones are required to be defined. When running the EOC be sure to set the Alpha talker to the Avatar so the EOCs can run correctly.


| Variable Name | Description | Context | Required |
|-|-|-|-|
|furn_pos |The location of the furniture. Supply pos variable from the examine action.<br/>```"furn_pos": { "context_val": "pos" }``` | EOC Context ||
|t_delay |The base amount of time it should take to hack this furniture. It is best defined before calling the EOC.<br/>```{ "math": [ "t_delay = time('20min')" ] }``` | EOC Context ||
|difficulty |The difficulty of hacking this furniture. To hack this furniture the player must beat this number by rolling a d4 and adding their hack skill | EOC Context ||
|t_radius |The radius around this furniture in which the ter-fur transform is applied. | EOC Context ||
|power_cost_mult | Multiplier applied to the total power cost of the hack if a tool or bionic is used. This can be used to increase the total power requirement of a hack without making it take longer to complete.| EOC Context |
|hack_minor_failure_eoc |The ID of the EOC to run when the player minorly fails at hacking this furniture. Leaving this blank will trigger the generic hack minor failure EOC to run. | User |
|hack_critical_failure |The ID of the EOC to run when the player critically fails at hacking this furniture. Leaving this blank will trigger the generic critical failure EOC to run. However, you will still need to add this furniture to the multi-lockdown ter-fur transform.| User
|hack_sucess_eoc | The ID of the EOC to run when the player succeeds at hacking the furniture. If this is left blank the generic success EOC will run. However, you will still need to add the furniture to the multi-unlock ter-fur transform.| User

```
"examine_action": {
"type": "effect_on_condition",
"effect_on_conditions": [
{
"id": "EOC_unlock_afs_display_case",
"effect": [
{ "math": [ "_t_delay = time('20 m')" ] },
{
"run_eocs": "EOC_start_lock_hack",
"variables": { "furn_pos": { "context_val": "pos" }, "t_delay": { "context_val": "t_delay" }, "difficulty": "10", "t_radius": "0" },
"alpha_talker": "avatar"
}
]
}
]
},
```

```
"examine_action": {
"type": "effect_on_condition",
"effect_on_conditions": [
{
"id": "EOC_unlock_afs_security_panel",
"effect": [
{ "math": [ "_t_delay = time('20 m')" ] },
{ "u_add_var": "hack_minor_failure_eoc", value: "EOC_Hack_Custom_Minor_Failure" },
{ "u_add_var": "hack_critical_fail_eoc", value: "EOC_Hack_Custom_Critical_Failure" },
{ "u_add_var": "hack_success_eoc", value: "EOC_Hack_Custom_Success" },
{
"run_eocs": "EOC_start_lock_hack",
"variables": { "furn_pos": { "context_val": "pos" }, "t_delay": { "context_val": "t_delay" }, "difficulty": "10", "t_radius": "6", "power_cost_mult": 2 },
"alpha_talker": "avatar"
}
]
}
]
},
```

### Hacking tools
Hacking tools require relatively little setup to work within our system. Simply make sure your item has the hack tool quality. Electronic tools require no adjustment and work right out of the gate. Bionic hacking tools also work straight away provided they are flagged with ```USE_BIONIC_POWER```. To make an item that doesn't consume charges at all simply flag it with ```HACK_NO_CHARGE```.

| Quality Level | Description |
|-|-|
| 1 | Electronics that could technically be used for hacking but offer virtually no benefits for it whatsoever. |
| 2 | Improvised Hacking tools that provide some benefit for hacking but fall short when compared to well-manufactured equipment.
| 3 | Small Corporate Infiltrator hacking gear. Providing a suite of hacking utilities. |
| 4 | Military Grade Hacking Gear. The stuff that UICA and the big Corpos use. |
| 5 | Elite Infiltrator Gear. The top-class equipment for that is still technically manufacturable. |
| 6 | Glittertech Hacking Equipment. Tools of this level aren't manufacturable anymore and can only be found in pre-discontinuity ruins.
10 changes: 10 additions & 0 deletions data/mods/Aftershock/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,15 @@
"id": "HIVE_MIND",
"type": "monster_flag",
"//": "This monster is part of a hive mind"
},
{
"id": "ACTIVE_HACK_TOOL",
"type": "json_flag",
"//": "This tool is being used to perform hacking operations."
},
{
"id": "HACK_NO_CHARGE",
"type": "json_flag",
"//": "This Hacking tool does not consume energy."
}
]
3 changes: 2 additions & 1 deletion data/mods/Aftershock/items/armor.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@
"weight_multiplier": 0.0,
"ememory_max": "1 TB"
}
]
],
"qualities": [ [ "HACK", 1 ] ]
},
{
"id": "xl_jeans",
Expand Down
11 changes: 6 additions & 5 deletions data/mods/Aftershock/items/esper_summons.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,46 @@
"PERSONAL",
"UNBREAKABLE",
"SEMITANGIBLE",
"HACK_NO_CHARGE",
"NO_SALVAGE",
"ZERO_WEIGHT",
"NO_UNLOAD",
"NO_RELOAD",
"INTEGRATED",
"MAGICAL"
],
"qualities": [ [ "HACK", 0 ] ]
"qualities": [ [ "HACK", 1 ] ]
},
{
"id": "electrokinetic_electrohack_2",
"type": "TOOL_ARMOR",
"name": { "str": "[Ψ]hacking interface" },
"description": "You can hack nearby devices.",
"copy-from": "electrokinetic_electrohack_1",
"qualities": [ [ "HACK", 1 ] ]
"qualities": [ [ "HACK", 2 ] ]
},
{
"id": "electrokinetic_electrohack_3",
"type": "TOOL_ARMOR",
"name": { "str": "[Ψ]hacking interface" },
"description": "You can hack nearby devices.",
"copy-from": "electrokinetic_electrohack_1",
"qualities": [ [ "HACK", 2 ] ]
"qualities": [ [ "HACK", 3 ] ]
},
{
"id": "electrokinetic_electrohack_4",
"type": "TOOL_ARMOR",
"name": { "str": "[Ψ]hacking interface" },
"description": "You can hack nearby devices.",
"copy-from": "electrokinetic_electrohack_1",
"qualities": [ [ "HACK", 3 ] ]
"qualities": [ [ "HACK", 4 ] ]
},
{
"id": "electrokinetic_electrohack_5",
"type": "TOOL_ARMOR",
"name": { "str": "[Ψ]hacking interface" },
"description": "You can hack nearby devices.",
"copy-from": "electrokinetic_electrohack_1",
"qualities": [ [ "HACK", 4 ] ]
"qualities": [ [ "HACK", 5 ] ]
}
]
2 changes: 1 addition & 1 deletion data/mods/Aftershock/items/tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@
"USES_BIONIC_POWER"
],
"charges_per_use": 1,
"qualities": [ [ "HACK", 2 ] ]
"qualities": [ [ "HACK", 4 ] ]
},
{
"id": "afs_internal_battery_compartment",
Expand Down
Loading

0 comments on commit bbc845d

Please sign in to comment.