Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
GuardianDll committed Jan 23, 2025
1 parent 5ad4199 commit 4da25fe
Show file tree
Hide file tree
Showing 13 changed files with 341 additions and 0 deletions.
10 changes: 10 additions & 0 deletions data/json/ammo_effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,16 @@
"type": "ammo_effect",
"explosion": { "power": 7980, "shrapnel": { "casing_mass": 8725, "fragment_mass": 0.5 } }
},
{
"id": "EXPLOSIVE_60mmHE",
"type": "ammo_effect",
"explosion": { "power": 25000, "shrapnel": 500 }
},
{
"id": "EXPLOSIVE_60mmHE2",
"type": "ammo_effect",
"explosion": { "power": 358, "shrapnel": 430 }
},
{
"id": "FLASHBANG",
"type": "ammo_effect",
Expand Down
43 changes: 43 additions & 0 deletions data/json/furniture_and_terrain/furniture_military.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[
{
"type": "furniture",
"id": "f_m224_mortar",
"name": "debug mortar",
"description": "debug mortar.",
"symbol": "#",
"color": "dark_gray",
"move_cost_mod": 2,
"coverage": 60,
"required_str": 10,
"flags": [ "MOUNTABLE", "SHORT", "FLAT_SURF" ],
"bash": {
"str_min": 12,
"str_max": 40,
"sound": "smash!",
"sound_fail": "whump.",
"items": [ { "item": "black_glass_shard", "count": [ 40, 80 ] } ]
},
"//range": [
"charge; muzzle velocity; min range, max range",
"0, 210, 70, 400 ",
"1, 415, 250, 1340",
"2, 560, 350, 2150",
"3, 680, 500, 2890",
"4, 810, 650, 3490",
"deviation in target range - 2% at best"
],
"examine_action": {
"type": "mortar",
"ammo": [ "mortar_60mm" ],
"range": 3490,
"aim_duration": "1 minutes",
"booster": "60mm_propellant",
"booster_distances": [
{ "amount": 4, "distance": 400 },
{ "amount": 3, "distance": 1340 },
{ "amount": 2, "distance": 2150 },
{ "amount": 1, "distance": 2890 }
]
}
}
]
48 changes: 48 additions & 0 deletions data/json/items/ammo/60mm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[
{
"id": "60mm_shell_m720a1",
"type": "AMMO",
"name": { "str": "high-explosive mortar shell" },
"description": "High-explosive mortar cartridge, designed to be used against troops, light vehicles, light bunkers or similar targets. Multioption fuse allows it to be set to function as proximity burst, impact burst, or delay burst.",
"variants": [
{
"id": "60mm_shell_m720",
"name": { "str": "M720A1 60 mm mortar shell (HE)", "str_pl": "M720A1 60 mm mortar shells (HE)" },
"description": "High-explosive mortar cartridge, designed to be used against troops, light vehicles, light bunkers or similar targets. Multioption fuse allows it to be set to function as proximity burst, impact burst, or delay burst."
}
],
"weight": "1700 g",
"//": "190 g of comp-b, so explosion power should be 250; let's pretend case mass is third of the rest of the weight, so 500 g",
"volume": "680 ml",
"longest_side": "376 mm",
"price": "400 USD",
"price_postapoc": "20 USD",
"flags": [ "IRREPLACEABLE_CONSUMABLE" ],
"material": [ { "type": "steel", "portion": 80 }, { "type": "powder", "portion": 20 } ],
"symbol": "=",
"color": "dark_gray",
"count": 1,
"stack_size": 1,
"ammo_type": "mortar_60mm",
"effects": [ "SPECIAL_COOKOFF", "NEVER_MISFIRES", "EXPLOSIVE_60mmHE" ]
},
{
"id": "60mm_shell_m768",
"copy-from": "60mm_shell_m720a1",
"type": "AMMO",
"name": { "str": "high-explosive mortar shell" },
"description": "High-explosive mortar cartridge, designed to be used against troops, light vehicles, light bunkers or similar targets. Multioption fuse allows it to be set to function as proximity burst, impact burst, or delay burst. This one is more modern version, both more safe and more powerful.",
"variants": [
{
"id": "60mm_shell_m768",
"name": { "str": "M768 60 mm mortar shell (HE)", "str_pl": "M768 60 mm mortar shells (HE)" },
"description": "High-explosive mortar cartridge, designed to be used against troops, light vehicles, light bunkers or similar targets. This one is more modern version, more safe and more powerful, but uses more simple impact fuze."
}
],
"weight": "1655 g",
"//": "358 g of pax-21, which is replacement for comp b - weaker (~1.0 tnt equivalent), but safer, so explosion power should be 358; let's pretend case mass is third of the rest of the weight, so 430 g",
"price": "600 USD",
"extend": { "effects": [ "EXPLOSIVE_60mmHE2" ] },
"delete": { "effects": [ "EXPLOSIVE_60mmHE" ] }
}
]
6 changes: 6 additions & 0 deletions data/json/items/ammo_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,12 @@
"name": "M235 66mm Incendiary TPA",
"default": "m235tpa"
},
{
"type": "ammunition_type",
"id": "mortar_60mm",
"name": "60 mm mortar cartridge",
"default": "60mm_shell_m720a1"
},
{
"type": "ammunition_type",
"id": "sling-ready_grenade",
Expand Down
25 changes: 25 additions & 0 deletions data/json/items/gun/60mm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[
{
"type": "GENERIC",
"id": "mortar_m224",
"name": { "str_sp": "light mortar" },
"description": "Lightweight Company Mortar System is a portable mortar that can be carried and used by a one person, even if much slower than with a full crew of three. Luckily, someone attached a bunch of firing tables to it. Whoever will use it should be prepared to spend plenty of time estimating distances and calculating correct elevation and rotation angles.",
"variants": [
{
"id": "mortar_m224",
"name": { "str": "60mm M224 mortar" },
"description": "Lightweight Company Mortar System is a portable mortar that can be carried and used by a one person, even if much slower than with a full crew of three. Luckily, someone attached a bunch of firing tables to it. Whoever will use it should be prepared to spend plenty of time estimating distances and calculating correct elevation and rotation angles."
}
],
"use_action": { "type": "deploy_furn", "furn_type": "f_m224_mortar" },
"category": "other",
"material": [ "steel" ],
"weight": "21100 g",
"volume": "48 L",
"longest_side": "100 cm",
"price": "11000 USD",
"price_postapoc": "20 USD",
"symbol": "q",
"color": "light_gray"
}
]
16 changes: 16 additions & 0 deletions data/json/items/tool/explosives.json
Original file line number Diff line number Diff line change
Expand Up @@ -1391,5 +1391,21 @@
"countdown_action": { "type": "explosion", "explosion": { "power": 69200, "shrapnel": { "casing_mass": 12000, "fragment_mass": 600 } } },
"flags": [ "BOMB", "TRADER_AVOID", "DANGEROUS" ],
"melee_damage": { "bash": 20 }
},
{
"id": "60mm_propellant",
"type": "GENERIC",
"name": { "str": "60 mm mortar propellant charge" },
"description": "Small explosive in a form of donut without a piece, this thing is designed to be attached on the mortar shell tail, to increase the projectile velocity and, therefore, it's range. Since the projectile it was connected to was already shot, you can only cut it for it's content.",
"weight": "50 g",
"//": "8 g of some unknown to me explosive material, let's assume comp b for simplicity",
"volume": "70 ml",
"longest_side": "45 mm",
"price": "14 USD",
"price_postapoc": "2 USD",
"flags": [ "IRREPLACEABLE_CONSUMABLE" ],
"material": [ { "type": "plastic", "portion": 80 }, { "type": "powder", "portion": 20 } ],
"symbol": "=",
"color": "dark_gray"
}
]
7 changes: 7 additions & 0 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -1134,5 +1134,12 @@
"verb": "infusing saline",
"based_on": "time",
"do_turn_eoc": "SALINE_INFUSION_eff"
},
{
"id": "ACT_MORTAR_AIMING",
"type": "activity_type",
"activity_level": "NO_EXERCISE",
"based_on": "speed",
"verb": "aiming the artillery"
}
]
3 changes: 3 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11399,6 +11399,9 @@ bool Character::sees( const Creature &critter ) const
if( dist < MAX_CLAIRVOYANCE && dist < clairvoyance() ) {
return true;
}
if( critter.has_flag( mon_flag_ALWAYS_VISIBLE ) ) {
return true;
}
// Only players can spot creatures through clairvoyance fields
if( is_avatar() && field_fd_clairvoyant.is_valid() &&
get_map().get_field( critter.pos_bub(), field_fd_clairvoyant ) ) {
Expand Down
140 changes: 140 additions & 0 deletions src/iexamine_actors.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
#include "iexamine_actors.h"

#include "ammo_effect.h"
#include "avatar.h"
#include "dialogue_helpers.h"
#include "effect_on_condition.h"
#include "explosion.h"
#include "game.h"
#include "game_inventory.h"
#include "generic_factory.h"
#include "inventory_ui.h"
#include "item.h"
#include "itype.h"
#include "line.h"
#include "map.h"
#include "mapgen_functions.h"
#include "mapgendata.h"
#include "map_iterator.h"
#include "messages.h"
#include "mtype.h"
#include "output.h"
#include "overmap_ui.h"
#include "overmapbuffer.h"
#include "veh_appliance.h"

static const ter_str_id ter_t_door_metal_c( "t_door_metal_c" );
static const ter_str_id ter_t_door_metal_locked( "t_door_metal_locked" );

static const skill_id skill_launcher( "launcher" );

static const activity_id ACT_MORTAR_AIMING( "ACT_MORTAR_AIMING" );

static const itype_id itype_60mm_propellant( "60mm_propellant" );

void appliance_convert_examine_actor::load( const JsonObject &jo, const std::string & )
{
optional( jo, false, "furn_set", furn_set );
Expand Down Expand Up @@ -285,3 +300,128 @@ std::unique_ptr<iexamine_actor> eoc_examine_actor::clone() const
{
return std::make_unique<eoc_examine_actor>( *this );
}

void mortar_examine_actor::call( Character &you, const tripoint_bub_ms &examp ) const
{
const_dialogue d( get_const_talker_for( you ), nullptr );

if( has_condition && !condition( d ) ) {
add_msg( _( condition_fail_msg ) );
return;
}

std::vector<ammotype> expected_ammo_types = ammo_type;
inventory_filter_preset preset( [expected_ammo_types]( const item_location & loc ) {
for( ammotype desired_ammo : expected_ammo_types ) {
if( desired_ammo == loc->ammo_type() ) {
return true;
};
}
return false;
} );
inventory_pick_selector inv_s( you, preset );
inv_s.add_nearby_items( PICKUP_RANGE );
inv_s.add_character_items( you );
inv_s.set_title( _( "Pick a projectile to be used." ) );

if( inv_s.empty() ) {
add_msg( _( "You have no rounds to use the mortar." ) );
return;
}

item_location loc;
if( inv_s.item_entry_count() == 0 ) {
add_msg( _( "You have no rounds to use the mortar." ) );
return;
} else if( inv_s.item_entry_count() == 1 ) {
loc = inv_s.get_only_choice().first;
} else {
loc = inv_s.execute();
}

if( loc == item_location::nowhere ) {
return;
}

// so we can write distance in proper units, and scale to in-game distance here
const int aim_range = range / 24;
const tripoint_abs_omt pos_omt = project_to<coords::omt>( get_map().get_abs( examp ) );
tripoint_abs_omt target = ui::omap::choose_point( "Pick a target.", pos_omt, false, aim_range );

if( target == tripoint_abs_omt::invalid ) {
return;
}

// 2 is bub size in OMT, prooly need some map scale constant, didn't found one fitting
if( rl_dist( you.pos_abs_omt(), target ) <= 2 ) {
add_msg( _( "Target is too close." ) );
return;
}

you.assign_activity( ACT_MORTAR_AIMING, to_moves<int>( aim_duration.evaluate( d ) ) );

if( booster ) {
int booster_qty = 0;
for( std::pair qty_dist_pair : booster_ranges ) {
if( rl_dist( you.pos_abs_omt(), target ) * 24 <= qty_dist_pair.second ) {
booster_qty = qty_dist_pair.first;
break;
}
}
item booster_item = item( booster );
you.i_add_or_drop( booster_item, booster_qty );
}

tripoint_abs_ms target_abs_ms = project_to<coords::ms>( target );
const int deviation = aim_deviation.evaluate( d );
// aim at the center of OMT, but with some deviation
// we just assume mortar projectiles fall at 90 degrees, duh
target_abs_ms.x() += rng_float( 12 + deviation, 12 - deviation );
target_abs_ms.y() += rng_float( 12 + deviation, 12 - deviation );
// we can have edge cases with it if, for example, we target radio tower (high building, but with small profile)
target_abs_ms.z() = overmap_buffer.highest_omt_point( project_to<coords::omt>( target_abs_ms ) );

for( ammo_effect_str_id ammo_eff : loc.get_item()->ammo_data()->ammo->ammo_effects ) {
explosion_handler::explosion( &you, get_map().get_bub( target_abs_ms ),
ammo_eff.obj().aoe_explosion_data );
}

loc->charges--;
if( loc->charges <= 0 ) {
loc.remove_item();
}
}

void mortar_examine_actor::load( const JsonObject &jo, const std::string & )
{
mandatory( jo, false, "ammo", ammo_type );
mandatory( jo, false, "range", range );
optional( jo, false, "booster", booster, itype_id::NULL_ID() );
if( jo.has_array( "booster_distances" ) ) {
int amount;
int distance;
for( const JsonObject jsobj : jo.get_array( "booster_distances" ) ) {
mandatory( jsobj, false, "amount", amount );
mandatory( jsobj, false, "distance", distance );
booster_ranges.emplace( amount, distance );
}
}
if( jo.has_member( "condition" ) ) {
read_condition( jo, "condition", condition, false );
has_condition = true;
}
optional( jo, false, "condition_fail_msg", condition_fail_msg, "You can't use this mortar." );

aim_deviation = get_dbl_or_var( jo, "aim_deviation", false, 0.0f );
aim_duration = get_duration_or_var( jo, "aim_duration", false, 0_seconds );
}

void mortar_examine_actor::finalize() const
{
// add different checks for validity
}

std::unique_ptr<iexamine_actor> mortar_examine_actor::clone() const
{
return std::make_unique<mortar_examine_actor>( *this );
}
24 changes: 24 additions & 0 deletions src/iexamine_actors.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define CATA_SRC_IEXAMINE_ACTORS_H

#include "iexamine.h"
#include "dialogue.h"

#include <map>

Expand Down Expand Up @@ -82,4 +83,27 @@ class eoc_examine_actor : public iexamine_actor
std::unique_ptr<iexamine_actor> clone() const override;
};

class mortar_examine_actor : public iexamine_actor
{
private:
std::vector<ammotype> ammo_type;
int range;
itype_id booster;
std::map<int, int> booster_ranges;
std::function<bool( const_dialogue const & )> condition;
bool has_condition = false;
std::string condition_fail_msg;
dbl_or_var aim_deviation;
duration_or_var aim_duration;

public:
explicit mortar_examine_actor( const std::string &type = "mortar" ): iexamine_actor( type ) {}

void load( const JsonObject &jo, const std::string & ) override;
void call( Character &you, const tripoint_bub_ms &examp ) const override;
void finalize() const override;

std::unique_ptr<iexamine_actor> clone() const override;
};

#endif // CATA_SRC_IEXAMINE_ACTORS_H
Loading

0 comments on commit 4da25fe

Please sign in to comment.