-
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#66 prepare the SE storage and allow SE to copy a nearby creature
- Loading branch information
Showing
4 changed files
with
204 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |