Skip to content

Commit

Permalink
#66 prepare the SE storage and allow SE to copy a nearby creature
Browse files Browse the repository at this point in the history
  • Loading branch information
Aelto committed Apr 11, 2022
1 parent 916a1b7 commit 68dbdd2
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 80 deletions.
10 changes: 7 additions & 3 deletions src/bestiary/bestiary.ws
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,18 @@ class RER_Bestiary {
}

public function getCreatureTypeFromEntity(entity: CEntity): CreatureType {
var type: CreatureType;
var hashed_name: string;
var i: int;

hashed_name = entity.GetReadableName();

return this.getCreatureTypeFromReadableName(hashed_name);
}

public function getCreatureTypeFromReadableName(readable_name: String): CreatureType {
var i: int;

for (i = 0; i < CreatureMAX; i += 1) {
if (this.entries[i].isCreatureHashedNameFromEntry(hashed_name)) {
if (this.entries[i].isCreatureHashedNameFromEntry(readable_name)) {
return i;
}
}
Expand Down
171 changes: 171 additions & 0 deletions src/static_encounters/placeholder_static_encounter.ws
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@

enum RER_PlaceholderStaticEncounterType {
/**
* When set with this the SE will use the ecosystem data to pick a random creature
* at every trigger.
*/
RER_PSET_LearnFromEcosystem = 0,

/**
* When set with this the SE will search for a nearby creature and will then spawn
* it again at every future trigger.
*
* If no creatures were found and a trigger happens, it will search for a copy again
* and if still no creature was found then it defaults to `LearnFromEcosystem`.
*/
RER_PSET_CopyNearbyCreature = 1
}

class RER_PlaceholderStaticEncounter extends RER_StaticEncounter {
public var type: RER_PlaceholderStaticEncounterType;

public var picked_creature_type: CreatureType;
default picked_creature_type = CreatureNONE;

/**
* Controls whether this static encounter can spawn its creatures even if
* there are other creatures in the area.
* true: can spawn
* false: cannot spawn
*/
private var ignore_creature_check: bool;

public function init(ignore_creature_check: bool): RER_PlaceholderStaticEncounter {
this.ignore_creature_check = ignore_creature_check;

return this;
}

/**
* override the function to return true whenever it finds a monster instead of
* a specific bestiary entry.
*/
private function areThereEntitiesWithSameTemplate(entities: array<CGameplayEntity>): bool {
var hashed_name: string;
var actor: CActor;
var i: int;

if (this.ignore_creature_check) {
return false;
}

for (i = 0; i < entities.Size(); i += 1) {
actor = (CActor)entities[i];

if (actor) {
if (actor.IsMonster()) {
return true;
}
}
}

return false;
}

/**
* override the function to return a random entry based on the surrounding
* ecosystem.
*
* warning: side effect, depending on the RER_PlaceholderStaticEncounterType
* it may run some additional functions.
*/
public latent function getBestiaryEntry(master: CRandomEncounters): RER_BestiaryEntry {
var filter: RER_SpawnRollerFilter;

filter = (new RER_SpawnRollerFilter in this)
.init();

if (this.type == StaticEncounterType_SMALL) {
filter
.setOffsets(
constants.large_creature_begin,
constants.large_creature_max,
0 // creature outside the offset have 0% chance to appear
);
}
else {
filter
.setOffsets(
constants.large_creature_begin,
constants.large_creature_max,
0 // creature outside the offset have 0% chance to appear
);
}

if (this.type == RER_PSET_LearnFromEcosystem) {
return master.bestiary.getRandomEntryFromBestiary(
master,
EncounterType_HUNTINGGROUND,
RER_flag(RER_BREF_IGNORE_SETTLEMENT, true),
filter
);
}
else if (this.type == RER_PSET_CopyNearbyCreature) {
// this placeholder static encounter has not yet found an entity to copy
if (this.picked_creature_type == CreatureNONE) {
this.picked_creature_type = this.findRandomNearbyHostileCreatureType(master);
}

// if it's still none then we default back to
// the LearnFromEcosystem behavior
if (this.picked_creature_type == CreatureNONE) {
return master.bestiary.getRandomEntryFromBestiary(
master,
EncounterType_HUNTINGGROUND,
RER_flag(RER_BREF_IGNORE_SETTLEMENT, true),
filter
);
}

return master.bestiary.getEntry(this.picked_creature_type);
}

NDEBUG("RER warning: RER_PlaceholderStaticEncounter::getBestiaryEntry(), returning RER_BestiaryEntryNull.");

return new RER_BestiaryEntryNull in master;
}

private function findRandomNearbyHostileCreatureType(master: CRandomEncounters): CreatureType {
var possible_types: array<CreatureType>;
var entities: array<CGameplayEntity>;
var current_type: CreatureType;
var current_entity: CEntity;
var i: int;

FindGameplayEntitiesCloseToPoint(
entities,
this.position,
this.radius + 20, // the +20 is to still catch monster on small radius in case they move
1 * (int)this.radius,
, // tags
FLAG_ExcludePlayer | FLAG_OnlyAliveActors | FLAG_Attitude_Hostile, // queryflags
thePlayer, // target
'CNewNPC'
);

for (i = 0; i < entities.Size(); i += 1) {
current_entity = (CEntity)entities[i];

if (current_entity) {
current_type = master.bestiary.getCreatureTypeFromReadableName(current_entity.GetReadableName());

if (current_type == CreatureNONE) {
continue;
}

possible_types.PushBack(current_type);
}
}

// note: we re-use i here instead of making a new variable for the array size
i = possible_types.Size();
if (i <= 0) {
return CreatureNONE;
}

// note: we re-use i here for the random index now
i = RandRange(i, 0);

return possible_types[i];
}
}
77 changes: 0 additions & 77 deletions src/static_encounters/static_encounter.ws
Original file line number Diff line number Diff line change
Expand Up @@ -159,80 +159,3 @@ class RER_StaticEncounter {
}

}

class RER_PlaceholderStaticEncounter extends RER_StaticEncounter {
/**
* Controls whether this static encounter can spawn its creatures even if
* there are other creatures in the area.
* true: can spawn
* false: cannot spawn
*/
private var can_overlap_with_others: bool;

public function init(can_overlap_with_others: bool): RER_PlaceholderStaticEncounter {
this.can_overlap_with_others = can_overlap_with_others;

return this;
}

/**
* override the function to return true whenever it finds a monster instead of
* a specific bestiary entry.
*/
private function areThereEntitiesWithSameTemplate(entities: array<CGameplayEntity>): bool {
var hashed_name: string;
var actor: CActor;
var i: int;

if (this.can_overlap_with_others) {
return false;
}

for (i = 0; i < entities.Size(); i += 1) {
actor = (CActor)entities[i];

if (actor) {
if (actor.IsMonster()) {
return true;
}
}
}

return false;
}

/**
* override the function to return a random entry based on the surrounding
* ecosystem.
*/
public latent function getBestiaryEntry(master: CRandomEncounters): RER_BestiaryEntry {
var filter: RER_SpawnRollerFilter;

filter = (new RER_SpawnRollerFilter in this)
.init();

if (this.type == StaticEncounterType_SMALL) {
filter
.setOffsets(
constants.large_creature_begin,
constants.large_creature_max,
0 // creature outside the offset have 0% chance to appear
);
}
else {
filter
.setOffsets(
constants.large_creature_begin,
constants.large_creature_max,
0 // creature outside the offset have 0% chance to appear
);
}

return master.bestiary.getRandomEntryFromBestiary(
master,
EncounterType_HUNTINGGROUND,
RER_flag(RER_BREF_IGNORE_SETTLEMENT, true),
filter
);
}
}
26 changes: 26 additions & 0 deletions src/storage/static_encounter.ws
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

class RER_StaticEncounterStorage extends RER_BaseStorage {
default id = 'RandomEncountersReworked';
default containerId = 'static_encounter';

var playthrough_seed: string;
var placeholder_static_encounters:
}

// an helper function to get ecosystem storage
function RER_loadStaticEncounterStorage(): RER_StaticEncounterStorage {
var storage: RER_StaticEncounterStorage;

storage = (RER_StaticEncounterStorage)GetModStorage()
.load('RandomEncountersReworked', 'static_encounter');

// the first time we load, there is no data so we have to create something from
// scratch.
if (!IsNameValid(storage.id) && !IsNameValid(storage.containerId)) {
LogChannel('RER', "RER_loadStaticEncounterStorage - instantiating new RER_StaticEncounterStorage");

storage = new RER_StaticEncounterStorage in thePlayer;
}

return storage;
}

0 comments on commit 68dbdd2

Please sign in to comment.