Skip to content

Commit

Permalink
Merge pull request #79136 from GuardianDll/artillery_potential
Browse files Browse the repository at this point in the history
I want to shoot a mortar (but first i need tools for it)
  • Loading branch information
Maleclypse authored Jan 17, 2025
2 parents eff9ffd + 353921d commit 25adee5
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 10 deletions.
102 changes: 102 additions & 0 deletions doc/JSON/EFFECT_ON_CONDITION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4047,6 +4047,108 @@ You teleport to `grass_place` with message `Yay!`; as `force` boolean is `true`,
}
```

#### `u_explosion``npc_explosion`
Creates an explosion at talker position or at passed coordinate

| Syntax | Optionality | Value | Info |
| --- | --- | --- | --- |
| "u_explosion", / "npc_explosion" | **mandatory** | explosion_data | copies the `explosion` field from `"type": "ammo_effect"`, but allows to use variables; defines what type of explosion is occuring |
| "target_var" | optional | [variable object](#variable-object) | if used, explosion will occur where the variable point to |

##### Valid talkers:

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
| ✔️ | ✔️ | ✔️ | ✔️ |||

##### Examples

You pick a tile using u_query_omt, then the explosion is caused at this position
```json
{
"type": "effect_on_condition",
"id": "TEST",
"effect": [
{ "u_query_omt": { "context_val": "pos" }, "message": "Select point to detonate." },
{
"if": { "math": [ "has_var(_pos)" ] },
"then": { "u_explosion": { "power": 50000, "max_noise": 35, "distance_factor": 0.5 }, "target_var": { "context_val": "pos" } },
"else": { "u_message": "Canceled" }
}
]
}
```

#### `u_query_omt``npc_query_omt`
Opens a map, and allow you to pick an overmap tile to store in variable

| Syntax | Optionality | Value | Info |
| --- | --- | --- | --- |
| "u_query_omt", / "npc_query_omt" | **mandatory** | [variable object](#variable-object) | variable, where coordinate be stored; if query is cancelled or player picks the tile farther than `distance_limit`, the variable is not stored, so conditoon like `{ "math": [ "has_var(_pos)" ] }` should be used to ensure variable was picked correctly |
| "message" | **mandatory** | string or [variable object](#variable-object) | message, that is printed on upper left corner of overmap UI |
| "target_var" | optional | [variable object](#variable-object) | if set, the center is not where the avatar is, but this coordinate |
| "distance_limit" | optional | int or [variable object](#variable-object) | default infinite; radius, which player is able to pick, otherwise no variable is stored. The border is highlighted for user |
| "spread" | optional | int or [variable object](#variable-object) | default 1; since map allows only precision of OMT level, the player choice is then converted to absolute coordinates, and adjusted to point to the center of overmap; spread respond for additional precision loss, "how far the tile gonna be picked from the center of OMT"; default value would result in you picking roughly the center of the OM |

##### Valid talkers:

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
| ✔️ ||||||

##### Examples

You pick a `distance_limit` using `num_input`, then open map, and if allowed OM is picked, print a message with `pos`
```json
{
"type": "effect_on_condition",
"id": "TEST",
"effect": [
{
"u_query_omt": { "context_val": "pos" },
"message": "Select point.",
"distance_limit": { "math": [ "num_input('distance', 10)" ] }
},
{
"if": { "math": [ "has_var(_pos)" ] },
"then": { "u_message": "<context_val:pos>" },
"else": { "u_message": "Canceled" }
}
]
}
```

You pick a `distance_limit` using `num_input`, then open map, and if allowed OM is picked, open another map, centered around the point you just picked
```json
{
"type": "effect_on_condition",
"id": "TEST_2",
"effect": [
{
"u_query_omt": { "context_val": "pos" },
"message": "Select point.",
"distance_limit": { "math": [ "num_input('distance', 10)" ] }
},
{
"if": { "math": [ "has_var(_pos)" ] },
"then": {
"u_query_omt": { "context_val": "pos2" },
"target_var": { "context_val": "pos" },
"message": "Select point.",
"distance_limit": 10
},
"else": { "u_message": "Canceled" }
},
{
"if": { "math": [ "has_var(_pos2)" ] },
"then": { "u_message": "pos2: <context_val:pos2>" },
"else": { "u_message": "Canceled" }
}
]
}
```


#### `u_die``npc_die`
You or an NPC will instantly die.
If the target is an item, it will be deleted.
Expand Down
2 changes: 2 additions & 0 deletions src/dialogue_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ struct abstract_str_or_var {
std::optional<T> default_val;
std::optional<std::function<T( const_dialogue const & )>> function;
std::string evaluate( const_dialogue const & ) const;
abstract_str_or_var() = default;
explicit abstract_str_or_var( T str ) : str_val( str ) {};
};

using str_or_var = abstract_str_or_var<std::string>;
Expand Down
107 changes: 107 additions & 0 deletions src/npctalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "effect_on_condition.h"
#include "enums.h"
#include "event_bus.h"
#include "explosion.h"
#include "faction.h"
#include "faction_camp.h"
#include "flag.h"
Expand Down Expand Up @@ -4352,6 +4353,110 @@ talk_effect_fun_t::func f_transform_radius( const JsonObject &jo, std::string_vi
};
}

talk_effect_fun_t::func f_explosion( const JsonObject &jo, std::string_view member,
const std::string_view, bool is_npc )
{
dbl_or_var dov_power;
dbl_or_var dov_distance_factor;
dbl_or_var dov_max_noise;
bool fire;
dbl_or_var dov_shrapnel_casing_mass = dbl_or_var( 0 );
dbl_or_var dov_shrapnel_fragment_mass = dbl_or_var( 0.005f );
dbl_or_var dov_shrapnel_recovery = dbl_or_var( 0 );
str_or_var dov_shrapnel_drop = str_or_var( "null" );

std::optional<var_info> target_var;
if( jo.has_member( "target_var" ) ) {
target_var = read_var_info( jo.get_object( "target_var" ) );
}

JsonObject jo_explosion = jo.get_object( member );
dov_power = get_dbl_or_var( jo_explosion, "power", true );
dov_distance_factor = get_dbl_or_var( jo_explosion, "distance_factor", false, 0.75f );
dov_max_noise = get_dbl_or_var( jo_explosion, "max_noise", false, 90000000 );
fire = jo_explosion.get_bool( "fire", false );
if( jo_explosion.has_int( "shrapnel" ) ) {
dov_shrapnel_casing_mass = get_dbl_or_var( jo_explosion, "casing_mass", true );
} else if( jo.has_object( "shrapnel" ) ) {
JsonObject jo_shr = jo_explosion.get_object( "shrapnel" );
dov_shrapnel_casing_mass = get_dbl_or_var( jo_shr, "casing_mass", true );
dov_shrapnel_fragment_mass = get_dbl_or_var( jo_shr, "fragment_mass", false, 0.08 );
dov_shrapnel_recovery = get_dbl_or_var( jo_shr, "recovery", false, 0 );
dov_shrapnel_drop = get_str_or_var( jo_shr.get_member( "drop" ), "drop", false, "null" );
}

return [target_var, dov_power, dov_distance_factor, dov_max_noise, fire, dov_shrapnel_casing_mass,
dov_shrapnel_fragment_mass, dov_shrapnel_recovery, dov_shrapnel_drop,
is_npc]( dialogue const & d ) {
tripoint_bub_ms target_pos;
if( target_var.has_value() ) {
tripoint_abs_ms abs_ms = get_tripoint_from_var( target_var, d, is_npc );
target_pos = get_map().get_bub( abs_ms );
} else {
target_pos = d.actor( is_npc )->pos_bub();
}
Creature &guy = *d.actor( is_npc )->get_creature();

explosion_data expl_data;
expl_data.power = dov_power.evaluate( d );
expl_data.distance_factor = dov_distance_factor.evaluate( d );
expl_data.max_noise = dov_max_noise.evaluate( d );
expl_data.fire = fire;
expl_data.shrapnel.casing_mass = dov_shrapnel_casing_mass.evaluate( d );
expl_data.shrapnel.fragment_mass = dov_shrapnel_fragment_mass.evaluate( d );
expl_data.shrapnel.recovery = dov_shrapnel_recovery.evaluate( d );
expl_data.shrapnel.drop = itype_id( dov_shrapnel_drop.evaluate( d ) );

explosion_handler::explosion( &guy, target_pos, expl_data );
};
}

talk_effect_fun_t::func f_query_omt( const JsonObject &jo, std::string_view member,
const std::string_view, bool is_npc )
{
std::optional<var_info> output_var;
if( jo.has_member( "output_var" ) ) {
output_var = read_var_info( jo.get_object( "output_var" ) );
}

var_info var = read_var_info( jo.get_object( member ) );

std::optional<var_info> target_var;
if( jo.has_member( "target_var" ) ) {
target_var = read_var_info( jo.get_object( "target_var" ) );
}

translation_or_var message = get_translation_or_var( jo.get_member( "message" ), "message", true );
dbl_or_var distance_limit = get_dbl_or_var( jo, "distance_limit", false, INT_MAX );
dbl_or_var spread = get_dbl_or_var( jo, "spread", false, 1.0 );

return [message, var, spread, distance_limit, target_var, is_npc]( dialogue & d ) {

Character const *ch = d.const_actor( is_npc )->get_const_character();
if( ch && ch->as_avatar() ) {

tripoint_abs_omt target_pos = d.actor( is_npc )->global_omt_location();
if( target_var.has_value() ) {
tripoint_abs_ms abs_ms = get_tripoint_from_var( target_var, d, is_npc );
target_pos = project_to<coords::omt>( abs_ms );
}

tripoint_abs_omt pick = ui::omap::choose_point( message.evaluate( d ), target_pos, false,
distance_limit.evaluate( d ) );
if( pick != tripoint_abs_omt::invalid ) {
tripoint_abs_ms abs_pos_ms = project_to<coords::ms>( pick );
// aim at the center of OMT
abs_pos_ms.x() += rng_float( 12 - spread.evaluate( d ), 12 + spread.evaluate( d ) );
abs_pos_ms.y() += rng_float( 12 - spread.evaluate( d ), 12 + spread.evaluate( d ) );
write_var_value( var.type, var.name, &d, abs_pos_ms.to_string() );
return;
}
return;
}
return;
};
}

talk_effect_fun_t::func f_transform_line( const JsonObject &jo, std::string_view member,
const std::string_view )
{
Expand Down Expand Up @@ -7218,6 +7323,8 @@ parsers = {
{ "u_forget_martial_art", "npc_forget_martial_art", jarg::member, &talk_effect_fun::f_forget_martial_art },
{ "u_location_variable", "npc_location_variable", jarg::object, &talk_effect_fun::f_location_variable },
{ "u_transform_radius", "npc_transform_radius", jarg::member | jarg::array, &talk_effect_fun::f_transform_radius },
{ "u_explosion", "npc_explosion", jarg::member, &talk_effect_fun::f_explosion },
{ "u_query_omt", "npc_query_omt", jarg::member, &talk_effect_fun::f_query_omt },
{ "u_set_goal", "npc_set_goal", jarg::member, &talk_effect_fun::f_npc_goal },
{ "u_set_guard_pos", "npc_set_guard_pos", jarg::member, &talk_effect_fun::f_guard_pos },
{ "u_learn_recipe", "npc_learn_recipe", jarg::member, &talk_effect_fun::f_learn_recipe },
Expand Down
26 changes: 19 additions & 7 deletions src/overmap_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2197,7 +2197,11 @@ static tripoint_abs_omt display()
} else {
data.fast_traveling = true;
}
return ret;
if( overmap_buffer.distance_limit( g->overmap_data.distance, g->overmap_data.origin_pos, ret ) ) {
return ret;
} else {
return tripoint_abs_omt::invalid;
}
}

} // namespace overmap_ui
Expand Down Expand Up @@ -2330,7 +2334,7 @@ std::pair<std::string, nc_color> oter_symbol_and_color( const tripoint_abs_omt &
cur_ter = overmap_buffer.ter( omp );
}

if( blink && opts.show_pc && !opts.hilite_pc && omp == opts.center ) {
if( blink && opts.show_pc && !opts.hilite_pc && omp == get_avatar().global_omt_location() ) {
// Display player pos, should always be visible
ret.second = player_character.symbol_color();
ret.first = "@";
Expand All @@ -2341,6 +2345,10 @@ std::pair<std::string, nc_color> oter_symbol_and_color( const tripoint_abs_omt &
ret.first = type->get_symbol();
} else if( opts.debug_scent && overmap_ui::get_scent_glyph( omp, ret.second, ret.first ) ) {
// get_scent_glyph has changed ret.second and ret.first if omp has a scent
} else if( blink &&
overmap_buffer.distance_limit_line( g->overmap_data.distance, g->overmap_data.origin_pos, omp ) ) {
ret.second = c_light_red;
ret.first = "X";
} else if( blink && overmap_buffer.is_marked_dangerous( omp ) ) {
ret.second = c_red;
ret.first = "X";
Expand Down Expand Up @@ -2525,26 +2533,30 @@ void ui::omap::display_zones( const tripoint_abs_omt &center, const tripoint_abs
overmap_ui::display();
}

tripoint_abs_omt ui::omap::choose_point( const std::string &message, bool show_debug_info )
tripoint_abs_omt ui::omap::choose_point( const std::string &message, bool show_debug_info,
const int distance )
{
return choose_point( message, get_player_character().global_omt_location(), show_debug_info );
return choose_point( message, get_player_character().global_omt_location(), show_debug_info,
distance );
}

tripoint_abs_omt ui::omap::choose_point( const std::string &message, const tripoint_abs_omt &origin,
bool show_debug_info )
bool show_debug_info, const int distance )
{
g->overmap_data = overmap_ui::overmap_draw_data_t();
g->overmap_data.message = message;
g->overmap_data.origin_pos = origin;
g->overmap_data.debug_info = show_debug_info;
g->overmap_data.distance = distance;
return overmap_ui::display();
}

tripoint_abs_omt ui::omap::choose_point( const std::string &message, int z, bool show_debug_info )
tripoint_abs_omt ui::omap::choose_point( const std::string &message, int z, bool show_debug_info,
const int distance )
{
tripoint_abs_omt pos = get_player_character().global_omt_location();
pos.z() = z;
return choose_point( message, pos, show_debug_info );
return choose_point( message, pos, show_debug_info, distance );
}

void ui::omap::setup_cities_menu( uilist &cities_menu, std::vector<city> &cities_container )
Expand Down
10 changes: 7 additions & 3 deletions src/overmap_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ void display_editor();
* @returns The absolute coordinates of the chosen point or
* point::invalid if canceled with Escape (or similar key).
*/
tripoint_abs_omt choose_point( const std::string &message = "", bool show_debug_info = false );
tripoint_abs_omt choose_point( const std::string &message = "", bool show_debug_info = false,
const int distance = INT_MAX );

/**
* Interactive point choosing; used as the map screen.
Expand All @@ -84,7 +85,8 @@ tripoint_abs_omt choose_point( const std::string &message = "", bool show_debug_
* @returns The absolute coordinates of the chosen point or
* point::invalid if canceled with Escape (or similar key).
*/
tripoint_abs_omt choose_point( const std::string &message, int z, bool show_debug_info = false );
tripoint_abs_omt choose_point( const std::string &message, int z, bool show_debug_info = false,
const int distance = INT_MAX );

/**
* Interactive point choosing; used as the map screen.
Expand All @@ -93,7 +95,7 @@ tripoint_abs_omt choose_point( const std::string &message, int z, bool show_debu
* point::invalid if canceled with Escape (or similar key).
*/
tripoint_abs_omt choose_point( const std::string &message, const tripoint_abs_omt &origin,
bool show_debug_info = false );
bool show_debug_info = false, const int distance = INT_MAX );

void setup_cities_menu( uilist &cities_menu, std::vector<city> &cities_container );

Expand Down Expand Up @@ -121,6 +123,8 @@ struct overmap_draw_data_t {
bool fast_traveling = false;
// message to display while using the map
std::string message;
// if there is a distance limit to pick the OMT
int distance = INT_MAX;

// draw zone location.
tripoint_abs_omt select = tripoint_abs_omt( -1, -1, -1 );
Expand Down
12 changes: 12 additions & 0 deletions src/overmapbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,18 @@ void overmapbuffer::toggle_explored( const tripoint_abs_omt &p )
om_loc.om->explored( om_loc.local ) = !om_loc.om->explored( om_loc.local );
}

bool overmapbuffer::distance_limit( const int distance, const tripoint_abs_omt &origin_pos,
const tripoint_abs_omt &picked_pos )
{
return rl_dist( origin_pos, picked_pos ) <= distance;
}

bool overmapbuffer::distance_limit_line( const int distance, const tripoint_abs_omt &origin_pos,
const tripoint_abs_omt &picked_pos )
{
return rl_dist( origin_pos, picked_pos ) == distance;
}

bool overmapbuffer::has_horde( const tripoint_abs_omt &p )
{
for( mongroup * const &m : overmap_buffer.monsters_at( p ) ) {
Expand Down
6 changes: 6 additions & 0 deletions src/overmapbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ class overmapbuffer
void delete_extra( const tripoint_abs_omt &p );
bool is_explored( const tripoint_abs_omt &p );
void toggle_explored( const tripoint_abs_omt &p );
// compare origin_pos with a limit
bool distance_limit( int distance, const tripoint_abs_omt &origin_pos,
const tripoint_abs_omt &picked_pos );
// same as distance_limit, used to draw a border, to visualize the limit
bool distance_limit_line( int distance, const tripoint_abs_omt &origin_pos,
const tripoint_abs_omt &picked_pos );
om_vision_level seen( const tripoint_abs_omt &p );
bool seen_more_than( const tripoint_abs_omt &p, om_vision_level test );
void set_seen( const tripoint_abs_omt &p, om_vision_level seen );
Expand Down

0 comments on commit 25adee5

Please sign in to comment.