Database
Want to save or read values but you don't want to hardcode it inside your code?
With KeyValues@
you can pretty much set up a database, one where non-programmers can also set values.
Here's an example:
Tips
- The array and functions could be used globally
- You only need to update the "database" once per game
- Depending on the complexity of your hate system, you can easily extend it to have more checks for ex. if Player passed Monday, or if the Player did something bad in a map, and so on...
- You can use Manners too for a more complex behavior system
(something Trashmasters started but never finished!)
AngelScript:
class HateFaction
{
// Name of our faction
string self;
// The factions we despise
array<string> hates;
}
// Note: this data or array is not saved to save file,
// make sure to reinitialize this on new/load game!
array<HateFaction> hateFactioners;
void UpdateHateDB()
{
// Clear out the array!
hateFactioners.removeRange(0,hateFactioners.size());
KeyValues@ pData = CreateKeyValues("P3_Database_Thingy");
pData.LoadFromFile("scripts/p3_database_thingy.txt");
for (KeyValues@ pKV = pData.GetFirstSubKey(); pKV != null; @pKV = pKV.GetNextKey())
{
// We are now inside "entry"
//Printf("Key Name: %s\n", pKV.GetName());
// Let's look specifically for "HateFactions", since we do have one!
KeyValues@ pSubs = pKV.FindKey("HateFactions");
if (pSubs != null)
{
for (KeyValues@ pSub = pSubs.GetFirstSubKey(); pSub != null; @pSub = pSub.GetNextKey())
{
string hater = pSub.GetName();
string hatee = pSub.GetString();
HateFaction faction;
// If there's an entry for hater already, don't add it to array,
// but add hater to the list!
bool bFound = false;
for (uint i = 0; i < hateFactioners.length(); i++)
{
if (hateFactioners[i].self == hater)
{
faction = hateFactioners[i];
bFound = true;
break;
}
}
// This is a safe check for already existing entries
// We don't really need to do this but here's one as an example!
if (bFound)
{
// We already did this once, continue looping...
if (faction.hates.find(hatee) != -1)
{
continue;
}
// Not found, then add hater to list!
}
else
{
faction.self = hater;
}
faction.hates.insertLast(hatee);
//Printf("Faction '%s' hates '%s'\n", hater, hatee);
// If it's not on the array already, insert!
if (!bFound)
hateFactioners.insertLast(faction);
}
}
}
// it is VERY important to delete KeyValues if we don't use it anymore!
pData.deleteThis();
}
// Then we could check the factions like this way
bool IsFactionHate(CP3SObj@ self, CP3SObj@ target)
{
// By default it should return false
if (@self == null || @target == null)
return false;
string selfFaction = self.GetFaction();
string targetFaction = target.GetFaction();
for (uint i = 0; i < hateFactioners.length(); i++)
{
// Got our faction...
if (hateFactioners[i].self == selfFaction)
{
// Let's iterate through self's hate list...
for (uint j = 0; j < hateFactioners[i].hates.length(); j++)
{
// Yes, we hate this faction!
if (hateFactioners[i].hates[j] == targetFaction)
{
return true;
}
}
}
}
return false;
}
...
// And an example of how you could use it
// (this function is inside a class which has a 'CP3SObj@ self' pointer)
// (the functions and the array is in a file which is global and has been included)
void SomeFunc()
{
if (self.GetTarget() == null)
return;
if (self.GetFaction() == "Player")
return;
if ( IsFactionHate(self, self.GetTarget()) )
{
self.Pattern("pt_attack");
}
else
{
self.Pattern("pt_end");
}
}
txt file in scripts folder:
"p3_database_thingy"
{
"entry"
{
"HateFactions"
{
// Hater // Hatee
"Animals" "Citizens"
"Animals" "Player"
"Animals" "Police"
"Animals" "Hobos"
"Citizens" "Animals"
"Police" "Animals"
}
// Factions LIKE this Faction, they will protect them at all costs
// (example of another entry for a DB thing)
"LikeFactions"
{
// Liker // Liked
"Police" "Police"
"Police" "Vendors"
"Vendors" "Vendors"
"Zealots" "Animals"
}
}
}