Author Topic: Treasures without gold?  (Read 325 times)

Legacy_BlueChicken2

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
Treasures without gold?
« on: January 15, 2014, 11:44:03 am »


               Hi,

I have been using the xp1 method to generate treasures on my module. I setup the chest with the items and the proper tag as described and it is working fine, except that while calling
CTG_CreateSpecificBaseTypeTreasure
it sometimes take the items I have on the chest, sometimes take gold.

I wold rather to not generate gold. I see I can pass up to three parameters to pick a treasure type, but I actually would like to have any type except gold. Rolling a d100 to decide in between the item passed to this function might work, but maybe is there a better way to write this?

This is my function to generate treasures:

edit: (is there a BBCode that adds highlight on the code block?)


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 < nChanceExtraTreasure){
            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 >= nChanceExtraTreasure) && (nRoll < nLowerTreasurePoint)){
            CTG_CreateSpecificBaseTypeTreasure(LowerTreasure(nTreasureKind), GetLastOpener(), oContainer);
            FloatingTextStringOnCreature("Meh, trash! ", GetLastOpener());
        }
        //get middle treasure
        else if((nRoll >= nLowerTreasurePoint) && (nRoll < nHigherTreasurePoint)){
            CTG_CreateSpecificBaseTypeTreasure(nTreasureKind, GetLastOpener(), oContainer);
            FloatingTextStringOnCreature("Treasure.", GetLastOpener());
        }
        //get Higher treasure
        else if(nRoll > nHigherTreasurePoint){
            FloatingTextStringOnCreature("OMG treasure!", GetLastOpener());
            CTG_CreateSpecificBaseTypeTreasure(HigherTreasure(nTreasureKind), GetLastOpener(), oContainer);
        }

        nTreasures--;
    }
}

               
               

               


                     Modifié par BlueChicken2, 15 janvier 2014 - 11:44 .
                     
                  


            

Legacy_BlueChicken2

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
Treasures without gold?
« Reply #1 on: January 15, 2014, 09:15:07 pm »


               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 .