It seems that CTG_CreateSpecificBaseTypeTreasure doesn't work the way I wanted. It re-creates the treasure everytime it is called, instead of add a new item for every call. The setup is similar: An area, with a predefined tag and some chests, that will be used to lotery the items.
I had to implement a system for this. Following the inc file:
#include "x0_i0_treasure"
const int UW_TREASURE_LOW = 0;
const int UW_TREASURE_MED = 1;
const int UW_TREASURE_HIGH = 2;
const int UW_TREASURE_UNIQ = 3;
/* Interal function prototypes below */
void RespawnObject(string sTag, int iType, location lLoc);
void DestroyTreasure(object oMe);
int DoneAlready(object oObject = OBJECT_SELF);
int HandleInvisibleLooter(object oPC, object oContainer = OBJECT_SELF);
void DestroyAndSetRespawn(float fDelay, string sTag, int iType, location lLoc, object oContainer = OBJECT_SELF);
int LowerTreasure(int nKind);
int HigherTreasure(int nKind);
void GenerateItem(int nTreasureKind, object oTarget);
/* This function should be called before open a chest. It avoids creating the treasure twice,
* handle the invisible players, set the respawn time for the chest and other smaller things.
*/
int InitializeTreasure(int nMinutes, object oObject = OBJECT_SELF);
/*
* This function should be used to generate treasure items.
* nTreasureKind: One of the constants defined on top of uw_treasure file
* nTreasures: Base number of treasures
* nChanceExtraTreasure: Chance to generate two treasures instead of one. Tested agains every treasure
* generation, including the extra ones.
* nMaxExtraTreasures: The number of treasures that can be generated extra.
* nChanceHigher: Chance from getting the treasure from a higher category. Tested once per treasure.
* nChanceLower: Chance from getting a treasure from a lower category. Tested once per treasure.
* oContainer: The object that will receive the treasure on its inventory.
*
*/
void GenericGenerateTreasure(int nTreasureKind, int nTreasures, int nChanceExtraTreasure,int nMaxExtraTreasures,
int nChanceHigher, int nChanceLower, object oContainer = OBJECT_SELF);
/**** IMPLEMENTATIONS - EXTERNAL FUNCTIONS ******/
int InitializeTreasure(int nMinutes, object oObject = OBJECT_SELF){
if(DoneAlready())
return FALSE;
object oLastOpener = GetLastOpener();
if(HandleInvisibleLooter(oLastOpener))
return FALSE;
location lLoc = GetLocation(oObject);
string sTag = GetTag(oObject);
int iType = GetObjectType(oObject);
float fDelay = 60.0 * IntToFloat(nMinutes);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUNBEAM), oObject);
DestroyAndSetRespawn(fDelay, sTag, iType, lLoc);
return TRUE;
}
void GenericGenerateTreasure(int nTreasureKind, int nTreasures, int nChanceExtraTreasure,int nMaxExtraTreasures,
int nChanceHigher, int nChanceLower, object oContainer = OBJECT_SELF){
int nExtraTreasurePoint = nChanceExtraTreasure;
//offset to stack with extra treasure roll
int nLowerTreasurePoint = nExtraTreasurePoint + nChanceLower;
//inverted offset, got if roll a higher value
int nHigherTreasurePoint = 100 - nChanceHigher;
//anything else (on the middle) is a standard treasure
int nExtraTreasuresCount = 0;
while(nTreasures > 0){
int nRoll = d100(1);
FloatingTextStringOnCreature("Roll: " + IntToString(nRoll), GetLastOpener());
// Get extra chances
if(nRoll < nExtraTreasurePoint){
FloatingTextStringOnCreature("Yey, extra treasure!", GetLastOpener());
nExtraTreasuresCount++;
if(nExtraTreasuresCount > nMaxExtraTreasures)
nTreasures += 2;
else
nTreasures++; //compensate being here and draw again
}
// Get lower treasure
else if((nRoll >= nExtraTreasurePoint) && (nRoll < nLowerTreasurePoint)){
GenerateItem(LowerTreasure(nTreasureKind), oContainer);
FloatingTextStringOnCreature("Meh, trash! ", GetLastOpener());
}
//get middle treasure
else if((nRoll >= nLowerTreasurePoint) && (nRoll < nHigherTreasurePoint)){
GenerateItem(nTreasureKind, oContainer);
FloatingTextStringOnCreature("Treasure.", GetLastOpener());
}
//get Higher treasure
else if(nRoll > nHigherTreasurePoint){
FloatingTextStringOnCreature("OMG treasure!", GetLastOpener());
GenerateItem(HigherTreasure(nTreasureKind), oContainer);
}
nTreasures--;
}
}
/**** IMPLEMENTATIONS - INTERNAL FUNCTIONS ******/
string TreasureKindToTag(int nTreasureKind){
switch(nTreasureKind){
case UW_TREASURE_LOW: return "UW_TREASURE_LOW";
case UW_TREASURE_MED: return "UW_TREASURE_MED";
case UW_TREASURE_HIGH: return "UW_TREASURE_HIGH";
case UW_TREASURE_UNIQ: return "UW_TREASURE_UNIQ";
}
return "UW_TREASURE_LOW";
}
object GetTreasureChest(int nTreasureKind){
object oWay = GetWaypointByTag("uw_treasure_ref");
return GetNearestObjectByTag(TreasureKindToTag(nTreasureKind), oWay);
}
int CountInventoryItems(object oObject){
int nCount = 0;
object oItem = GetFirstItemInInventory(oObject);
while(GetIsObjectValid(oItem)){
nCount++;
oItem = GetNextItemInInventory(oObject);
}
FloatingTextStringOnCreature("Chest number item: "+IntToString(nCount) , GetLastOpener());
return nCount;
}
void GenerateItem(int nTreasureKind, object oTarget){
FloatingTextStringOnCreature("Generating Item...", GetLastOpener());
object oChest = GetTreasureChest(nTreasureKind);
int nSelectedItemIndex = Random(CountInventoryItems(oChest));
int i = 0;
object oItem = GetFirstItemInInventory(oChest);
while(i != nSelectedItemIndex){
oItem = GetNextItemInInventory(oChest);
i++;
}
CopyItem(oItem, oTarget);
}
int LowerTreasure(int nKind){
if(nKind == TREASURE_TYPE_MED)
return TREASURE_TYPE_LOW;
if(nKind == TREASURE_TYPE_HIGH)
return TREASURE_TYPE_MED;
if(nKind == TREASURE_TYPE_UNIQUE)
return TREASURE_TYPE_HIGH;
return TREASURE_TYPE_LOW;
}
int HigherTreasure(int nKind){
if(nKind == TREASURE_TYPE_LOW)
return TREASURE_TYPE_MED;
if(nKind == TREASURE_TYPE_MED)
return TREASURE_TYPE_HIGH;
if(nKind == TREASURE_TYPE_HIGH)
return TREASURE_TYPE_UNIQUE;
return TREASURE_TYPE_LOW;
}
void RespawnObject(string sTag, int iType, location lLoc){
string sResRef = GetStringLowerCase(GetStringLeft(sTag, 16));
CreateObject(iType, sResRef, lLoc);
}
void DestroyTreasure(object oMe)
{
object o = GetFirstItemInInventory(oMe);
while(GetIsObjectValid(o)) {
SetPlotFlag(o, FALSE);
DestroyObject(o, 0.0f);
o =GetNextItemInInventory(oMe);
}
}
int DoneAlready(object oObject = OBJECT_SELF) {
if (GetLocalInt(oObject,"NW_DO_ONCE") != 0)
return TRUE;
SetLocalInt(oObject,"NW_DO_ONCE",1);
ShoutDisturbed();
return FALSE;
}
int HandleInvisibleLooter(object oPC, object oContainer = OBJECT_SELF){
int invisible = GetHasSpellEffect(SPELL_INVISIBILITY, oPC) ||
GetHasSpellEffect(SPELL_IMPROVED_INVISIBILITY, oPC) ||
GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oPC);
int ethereal = GetHasSpellEffect(SPELL_ETHEREALNESS, oPC) ||
GetHasSpellEffect(SPELL_SANCTUARY, oPC);
if( invisible || ethereal) {
DestroyTreasure(oContainer);
string sMsg;
if(GetLocalInt(oPC, "GS_LOOTER") == 1) {
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionJumpToLocation(GetLocation(GetWaypointByTag("prison"))));
SendMessageToPC(oPC, "You have been sent to jail for looting items while invisible.");
} else {
CreateItemOnObject("gslootlib", oPC, 1);
SetLocalInt(oPC, "GS_LOOTER", 1);
sMsg = "You cannot be invisible while looting for treasure, YOU HAVE BEEN WARNED!";
}
FloatingTextStringOnCreature(sMsg, oPC, TRUE);
FloatingTextStringOnCreature(sMsg, oPC, TRUE);
FloatingTextStringOnCreature(sMsg, oPC, TRUE);
return TRUE;
}
return FALSE;
}
void DestroyAndSetRespawn(float fDelay, string sTag, int iType, location lLoc, object oContainer = OBJECT_SELF){
SetPlotFlag(oContainer, FALSE);
DestroyObject(oContainer, 0.0);
AssignCommand(GetArea(oContainer), DelayCommand(fDelay, RespawnObject(sTag, iType, lLoc)));
}
and a sample file of how to use it (to be used on the ondestroy and onopen flag of the object - it should be always locked, by the way)
#include "uw_treasure"
int nTreasureKind = UW_TREASURE_LOW;
const int nTreasures = 2;
const int nChanceExtraTreasure = 8;
const int nMaxExtraTreasures = 3;
const int nChanceHigher = 12;
const int nChanceLower = 0;
const int nMinutes = 15; //respawn chest time
void main() {
InitializeTreasure(nMinutes);
GenericGenerateTreasure(
nTreasureKind,
nTreasures,
nChanceExtraTreasure,
nMaxExtraTreasures,
nChanceHigher,
nChanceLower);
}
Modifié par BlueChicken2, 15 janvier 2014 - 09:15 .