Skip to content

Commit

Permalink
Add relic activation ability (#42391)
Browse files Browse the repository at this point in the history
* Add relic activation ability

Encapsulate all the charge info about relics in a relic_charge_info
struct. Additionally, add a template struct, and allow using this to
specify variants of relic charge info in relic_procgen_data.

Add simple placeholder versions to this data, along with active effects
for it to provide.

Attempt to recharge relics when processing them.

* Update src/relic.cpp

* Update src/relic.cpp

Co-authored-by: Curtis Merrill <[email protected]>
  • Loading branch information
anothersimulacrum and KorGgenT authored Aug 4, 2020
1 parent e36109d commit e1ebc7b
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 12 deletions.
39 changes: 36 additions & 3 deletions data/json/artifact/relic_procgen_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
{
"type": "relic_procgen_data",
"id": "cult",
"charge_types": [
{
"weight": 100,
"charges": { "range": [ 0, 3 ], "power": 25 },
"charges_per_use": { "range": [ 1, 1 ], "power": 25 },
"max_charges": { "range": [ 1, 3 ], "power": 25 },
"recharge_type": "periodic",
"time": [ "3 h", "6 h" ]
}
],
"active_procgen_values": [ { "weight": 100, "spell_id": "AEA_PAIN", "base_power": 50 } ],
"passive_add_procgen_values": [
{ "weight": 100, "min_value": -1, "max_value": 1, "type": "STRENGTH", "increment": 1, "power_per_increment": 250 },
{
Expand Down Expand Up @@ -37,12 +48,23 @@
"power_per_increment": 200
}
],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" } ],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" }, { "weight": 100, "value": "active_enchantment" } ],
"items": [ { "weight": 100, "item": "spoon" } ]
},
{
"type": "relic_procgen_data",
"id": "netherum_tunnels",
"charge_types": [
{
"weight": 100,
"charges": { "range": [ 0, 3 ], "power": 25 },
"charges_per_use": { "range": [ 1, 1 ], "power": 25 },
"max_charges": { "range": [ 1, 3 ], "power": 25 },
"recharge_type": "periodic",
"time": [ "3 h", "6 h" ]
}
],
"active_procgen_values": [ { "weight": 100, "spell_id": "AEA_PAIN", "base_power": 50 } ],
"passive_add_procgen_values": [
{ "weight": 100, "min_value": -1, "max_value": 1, "type": "STRENGTH", "increment": 1, "power_per_increment": 250 },
{
Expand Down Expand Up @@ -78,12 +100,23 @@
"power_per_increment": 200
}
],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" } ],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" }, { "weight": 100, "value": "active_enchantment" } ],
"items": [ { "weight": 100, "item": "spoon" } ]
},
{
"type": "relic_procgen_data",
"id": "alien_reality",
"charge_types": [
{
"weight": 100,
"charges": { "range": [ 0, 3 ], "power": 25 },
"charges_per_use": { "range": [ 1, 1 ], "power": 25 },
"max_charges": { "range": [ 1, 3 ], "power": 25 },
"recharge_type": "periodic",
"time": [ "3 h", "6 h" ]
}
],
"active_procgen_values": [ { "weight": 100, "spell_id": "AEA_PAIN", "base_power": 50 } ],
"passive_add_procgen_values": [
{ "weight": 100, "min_value": -1, "max_value": 1, "type": "STRENGTH", "increment": 1, "power_per_increment": 250 },
{
Expand Down Expand Up @@ -119,7 +152,7 @@
"power_per_increment": 200
}
],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" } ],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" }, { "weight": 100, "value": "active_enchantment" } ],
"items": [ { "weight": 100, "item": "spoon" } ]
}
]
26 changes: 26 additions & 0 deletions doc/ARTIFACTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ The procedural generation of artifacts is defined in Json. The object looks like
{
"type": "relic_procgen_data",
"id": "cult",
"charge_types": [
{
"weight": 100,
"charges": { "range": [ 0, 3 ], "power": 25 },
"charges_per_use":{ "range": [ 1, 1 ], "power": 25 },
"max_charges": { "range": [ 1, 3 ], "power": 25 },
"recharge_type": "periodic",
"time": [ "3 h", "6 h" ]
}
],
"active_procgen_values": [ { "weight": 100, "spell_id": "AEA_PAIN" } ],
"passive_add_procgen_values": [
{
"weight": 100,
Expand All @@ -36,6 +47,21 @@ The procedural generation of artifacts is defined in Json. The object looks like
}
```

### charge_types

The various ways this artifact can charge and use charges.

- **charges** the number of charges this artifact starts with - a random value between the two ones in 'range' are picked, and power is the power value.
- **charges_per_use** how many charges you spend with each use of this artifact - a random value between the two ones in 'range' are picked, and power is the power value.
- **max_charges** The maximum number of charges this artifact can have. - a random value between the two ones in 'range' are picked, and power is the power value.
- **recharge_type** How this artifact recharges
- **time** The amount of time this artifact takes to recharge - a random value between the two ones provided is picked.

#### recharge_types

- **none** This artifact does not recharge
- **periodic** This artifact takes 'time' amount of time to recharge

### passive_add_procgen_values and passive_mult_procgen_values

As the names suggest, these are *passive* benefits/penalties to having the artifact (ie. always present without activating the artifact's abilities). **Add** values add or subtract from existing scores, and **mult** values multiply them. These are entered as a list of possible 'abilities' the artifact could get. It does not by default get all these abilities, rather when it spawns it selects from the list provided.
Expand Down
18 changes: 15 additions & 3 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1586,11 +1586,15 @@ bool avatar::wield( item &target, const int obtain_cost )
bool avatar::invoke_item( item *used, const tripoint &pt )
{
const std::map<std::string, use_function> &use_methods = used->type->use_methods;
const int num_methods = use_methods.size();

if( use_methods.empty() ) {
const bool has_relic = used->is_relic();
if( use_methods.empty() && !has_relic ) {
return false;
} else if( use_methods.size() == 1 ) {
} else if( num_methods == 1 && !has_relic ) {
return invoke_item( used, use_methods.begin()->first, pt );
} else if( num_methods == 0 && has_relic ) {
return used->use_relic( *this, pt );
}

uilist umenu;
Expand All @@ -1603,6 +1607,10 @@ bool avatar::invoke_item( item *used, const tripoint &pt )
umenu.addentry_desc( MENU_AUTOASSIGN, res.success(), MENU_AUTOASSIGN, e.second.get_name(),
res.str() );
}
if( has_relic ) {
umenu.addentry_desc( MENU_AUTOASSIGN, true, MENU_AUTOASSIGN, _( "Use relic" ),
_( "Activate this relic." ) );
}

umenu.desc_enabled = std::any_of( umenu.entries.begin(),
umenu.entries.end(), []( const uilist_entry & elem ) {
Expand All @@ -1612,7 +1620,11 @@ bool avatar::invoke_item( item *used, const tripoint &pt )
umenu.query();

int choice = umenu.ret;
if( choice < 0 || choice >= static_cast<int>( use_methods.size() ) ) {
// Use the relic
if( choice == num_methods ) {
return used->use_relic( *this, pt );
}
if( choice < 0 || choice >= num_methods ) {
return false;
}

Expand Down
10 changes: 10 additions & 0 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4720,6 +4720,9 @@ std::string item::tname( unsigned int quantity, bool with_prefix, unsigned int t
if( gunmod_find( itype_barrel_small ) ) {
modtext += _( "sawn-off " );
}
if( is_relic() && relic_data->max_charges() > 0 && relic_data->charges_per_use() > 0 ) {
tagtext += string_format( " (%d/%d)", relic_data->charges(), relic_data->max_charges() );
}
if( has_flag( flag_DIAMOND ) ) {
modtext += std::string( pgettext( "Adjective, as in diamond katana", "diamond" ) ) + " ";
}
Expand Down Expand Up @@ -9312,6 +9315,11 @@ void item::overwrite_relic( const relic &nrelic )
this->relic_data = cata::make_value<relic>( nrelic );
}

bool item::use_relic( Character &guy, const tripoint &pos )
{
return relic_data->activate( guy, pos );
}

void item::process_relic( Character *carrier )
{
if( !is_relic() ) {
Expand All @@ -9329,6 +9337,8 @@ void item::process_relic( Character *carrier )
ench.activate_passive( *carrier );
}

relic_data->try_recharge();

// Recalculate, as it might have changed (by mod_*_bonus above)
carrier->str_cur = carrier->get_str();
carrier->int_cur = carrier->get_int();
Expand Down
2 changes: 2 additions & 0 deletions src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,8 @@ class item : public visitable<item>
*/
void on_damage( int qty, damage_type dt );

bool use_relic( Character &guy, const tripoint &pos );

/**
* Name of the item type (not the item), with proper plural.
* This is only special when the item itself has a special name ("name" entry in
Expand Down
2 changes: 2 additions & 0 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2879,6 +2879,8 @@ void player::use( item_location loc )
} else {
add_msg( m_info, need_splint.str() );
}
} else if( used.is_relic() ) {
invoke_item( &used, loc.position() );
} else {
add_msg( m_info, _( "You can't do anything interesting with your %s." ),
used.tname() );
Expand Down
Loading

0 comments on commit e1ebc7b

Please sign in to comment.