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

feat(port): start work on porting relic generation #4171

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 14 commits
Commits
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
125 changes: 125 additions & 0 deletions data/json/artifact/relic_procgen_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
[
{
"type": "relic_procgen_data",
"id": "cult",
"passive_add_procgen_values": [
{ "weight": 100, "min_value": -1, "max_value": 1, "type": "STRENGTH", "increment": 1, "power_per_increment": 250 },
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "DEXTERITY",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "PERCEPTION",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "INTELLIGENCE",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -100,
"max_value": 25,
"type": "SPEED",
"increment": 5,
"power_per_increment": 200
}
],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" } ],
"items": [ { "weight": 100, "item": "spoon" } ]
},
{
"type": "relic_procgen_data",
"id": "netherum_tunnels",
"passive_add_procgen_values": [
{ "weight": 100, "min_value": -1, "max_value": 1, "type": "STRENGTH", "increment": 1, "power_per_increment": 250 },
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "DEXTERITY",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "PERCEPTION",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "INTELLIGENCE",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -100,
"max_value": 25,
"type": "SPEED",
"increment": 5,
"power_per_increment": 200
}
],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" } ],
"items": [ { "weight": 100, "item": "spoon" } ]
},
{
"type": "relic_procgen_data",
"id": "alien_reality",
"passive_add_procgen_values": [
{ "weight": 100, "min_value": -1, "max_value": 1, "type": "STRENGTH", "increment": 1, "power_per_increment": 250 },
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "DEXTERITY",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "PERCEPTION",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "INTELLIGENCE",
"increment": 1,
"power_per_increment": 250
},
{
"weight": 100,
"min_value": -100,
"max_value": 25,
"type": "SPEED",
"increment": 5,
"power_per_increment": 200
}
],
"type_weights": [ { "weight": 100, "value": "passive_enchantment_add" } ],
"items": [ { "weight": 100, "item": "spoon" } ]
}
]
76 changes: 76 additions & 0 deletions doc/src/content/docs/en/mod/json/reference/items/relics.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,79 @@ optional):
| `rad` | Character or map tile must be irradiated |
| `wet` | Character must be wet, or it's raining |
| `sky` | Character must be above z=0 |

# Generation

The procedural generation of artifacts is defined in Json. The object looks like the following:

```json
{
"type": "relic_procgen_data",
"id": "cult",
"passive_add_procgen_values": [
{
"weight": 100,
"min_value": -1,
"max_value": 1,
"type": "STRENGTH",
"increment": 1,
"power_per_increment": 250
}
],
"passive_mult_procgen_values": [
{
"weight": 100,
"min_value": -1.5,
"max_value": 1.5,
"type": "STRENGTH",
"increment": 0.1,
"power_per_increment": 250
}
],
"type_weights": [{ "weight": 100, "value": "passive_enchantment_add" }],
"items": [{ "weight": 100, "item": "spoon" }]
}
```

## 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.

- **weight:** the weight of this value in the list, to be chosen randomly
- **min_value:** the minimum possible value for this value type. for add must be an integer, for
mult it can be a float
- **max_value:** the maximum possible value for this value type. for add must be an integer, for
mult it can be a float
- **type:** the type of enchantment value. see MAGIC.md for detailed documentation on enchantment
values
- **increment:** the increment that is used for the power multiplier
- **power_per_increment:** the power value per increment

## type_weights

This determines the relative weight of the 'add' and 'mult' types. When generated, an artifact first
decides if it is going to apply an 'add' or a 'mult' ability based on the type_weights of each. Then
it uses the weights of the entries under the selected type to pick an ability. This continues
cycling until the artifact reaches the defined power level. Possible values right now that are
functional are:

- passive_enchantment_add
- passive_enchantment_mult

This must be included in a dataset or it could cause a crash.

## items

This provides a list of possible items that this artifact can spawn as, if it appears randomly in a
hard-coded map extra.

## Power Level

An artifact's power level is a summation of its attributes. For example, each point of strength
addition in the above object, the artifact is a +250 power, so an artifact with +2 strength would
have a power level of 500. similarly, if an artifact had a strength multiplier of 0.8, it would have
a power level of -500.
2 changes: 1 addition & 1 deletion src/debug_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1637,7 +1637,7 @@ void debug()
artifact_natural_property prop = static_cast<artifact_natural_property>( rng( ARTPROP_NULL + 1,
ARTPROP_MAX - 1 ) );
m.create_anomaly( *center, prop );
m.spawn_natural_artifact( *center, prop );
m.spawn_artifact( *center, relic_procgen_id( "alien_reality" ) );
}
break;

Expand Down
1 change: 1 addition & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ void DynamicDataLoader::initialize()
add( "json_flag", &json_flag::load_all );
add( "mutation_flag", &json_trait_flag::load_all );
add( "fault", &fault::load_fault );
add( "relic_procgen_data", &relic_procgen_data::load_relic_procgen_data );
add( "field_type", &field_types::load );
add( "weather_type", &weather_types::load );
add( "ammo_effect", &ammo_effects::load );
Expand Down
5 changes: 5 additions & 0 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9217,6 +9217,11 @@ std::vector<trait_id> item::mutations_from_wearing( const Character &guy ) const
return muts;
}

void item::overwrite_relic( const relic &nrelic )
{
this->relic_data = cata::make_value<relic>( nrelic );
}

void item::process_relic( Character &carrier )
{
if( !is_relic() ) {
Expand Down
1 change: 1 addition & 0 deletions src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@

template<typename... T>
inline static detached_ptr<item> spawn( T... args ) {
return detached_ptr<item>( new item( std::forward<T>( args )... ) ) ;

Check failure on line 293 in src/item.h

View workflow job for this annotation

GitHub Actions / build

no matching constructor for initialization of 'item' [clang-diagnostic-error]

Check failure on line 293 in src/item.h

View workflow job for this annotation

GitHub Actions / GCC 12, Ubuntu, Curses

no matching function for call to ‘item::item(detached_ptr<item>)’
}

inline static item *spawn_temporary( const item &source ) {
Expand Down Expand Up @@ -1214,6 +1214,7 @@
* @param pos The location of the artifact (should be the player location if carried).
*/
void process_artifact( player *carrier, const tripoint &pos );
void overwrite_relic( const relic &nrelic );
void process_relic( Character &carrier );

bool destroyed_at_zero_charges() const;
Expand Down
42 changes: 25 additions & 17 deletions src/magic_enchantment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,6 @@
#include "string_id.h"
#include "units.h"

template <typename E> struct enum_traits;

template<>
struct enum_traits<enchantment::has> {
static constexpr enchantment::has last = enchantment::has::NUM_HAS;
};

template<>
struct enum_traits<enchantment::condition> {
static constexpr enchantment::condition last = enchantment::condition::NUM_CONDITION;
};

template<>
struct enum_traits<enchant_vals::mod> {
static constexpr enchant_vals::mod last = enchant_vals::mod::NUM_MOD;
};

namespace io
{
// *INDENT-OFF*
Expand Down Expand Up @@ -401,6 +384,31 @@ void enchantment::force_add( const enchantment &rhs )
}
}

void enchantment::set_has( enchantment::has value )
{
active_conditions.first = value;
}

void enchantment::add_value_add( enchant_vals::mod value, int add_value )
{
values_add[value] = add_value;
}

void enchantment::add_value_mult( enchant_vals::mod value, float mult_value )
{
values_multiply[value] = mult_value;
}

void enchantment::add_hit_me( const fake_spell &sp )
{
hit_me_effect.push_back( sp );
}

void enchantment::add_hit_you( const fake_spell &sp )
{
hit_you_effect.push_back( sp );
}

int enchantment::get_value_add( const enchant_vals::mod value ) const
{
const auto found = values_add.find( value );
Expand Down
26 changes: 26 additions & 0 deletions src/magic_enchantment.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vector>

#include "calendar.h"
#include "enum_traits.h"
#include "magic.h"
#include "type_id.h"

Expand Down Expand Up @@ -99,6 +100,14 @@ class enchantment
// adds two enchantments together and ignores their conditions
void force_add( const enchantment &rhs );

void set_has( has value );

void add_value_add( enchant_vals::mod value, int add_value );
void add_value_mult( enchant_vals::mod value, float mult_value );

void add_hit_me( const fake_spell &sp );
void add_hit_you( const fake_spell &sp );

int get_value_add( enchant_vals::mod value ) const;
double get_value_multiply( enchant_vals::mod value ) const;

Expand Down Expand Up @@ -172,4 +181,21 @@ class enchantment
const fake_spell &sp ) const;
};

template <typename E> struct enum_traits;

template<>
struct enum_traits<enchantment::has> {
static constexpr enchantment::has last = enchantment::has::NUM_HAS;
};

template<>
struct enum_traits<enchantment::condition> {
static constexpr enchantment::condition last = enchantment::condition::NUM_CONDITION;
};

template<>
struct enum_traits<enchant_vals::mod> {
static constexpr enchant_vals::mod last = enchant_vals::mod::NUM_MOD;
};

#endif // CATA_SRC_MAGIC_ENCHANTMENT_H
13 changes: 6 additions & 7 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4349,15 +4349,14 @@ std::vector<detached_ptr<item>> map::spawn_items( const tripoint &p,
return ret;
}

void map::spawn_artifact( const tripoint &p )
void map::spawn_artifact( const tripoint &p, const relic_procgen_id &id )
{
add_item_or_charges( p, item::spawn( new_artifact(), calendar::start_of_cataclysm ) );
}
relic_procgen_data::generation_rules rules;
rules.max_attributes = 5;
rules.power_level = 1000;
rules.max_negative_power = -2000;

void map::spawn_natural_artifact( const tripoint &p, artifact_natural_property prop )
{
add_item_or_charges( p, item::spawn( new_natural_artifact( prop ),
calendar::start_of_cataclysm ) );
add_item_or_charges( p, item::spawn( id->create_item( rules ) ) );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the item::spawn call here, you can just use id->create_item raw. It won't cause any real problems but it's spawning a new copy of the item and deleting the original.

Other than that it looks good though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You sure that's the only problem? Because as it is now it doesn't compile because I haven't finished converting all functions to use item identity stuff, if I recall.

}

void map::spawn_item( const tripoint &p, const itype_id &type_id,
Expand Down
6 changes: 4 additions & 2 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class mapgendata;
class monster;
class optional_vpart_position;
class player;
class relic_procgen_data;
class submap;
template<typename Tripoint>
class tripoint_range;
Expand Down Expand Up @@ -99,6 +100,8 @@ namespace cata
template <class T> class poly_serialized;
} // namespace cata

using relic_procgen_id = string_id<relic_procgen_data>;

class map_stack : public item_stack
{
private:
Expand Down Expand Up @@ -1200,8 +1203,7 @@ class map
detached_ptr<item> i_rem( point p, item *it ) {
return i_rem( tripoint( p, abs_sub.z ), it );
}
void spawn_artifact( const tripoint &p );
void spawn_natural_artifact( const tripoint &p, artifact_natural_property prop );
void spawn_artifact( const tripoint &p, const relic_procgen_id &id );
void spawn_item( const tripoint &p, const itype_id &type_id,
unsigned quantity = 1, int charges = 0,
const time_point &birthday = calendar::start_of_cataclysm, int damlevel = 0 );
Expand Down
Loading
Loading