//:://////////////////////////////////////////////////
//:: X0_I0_DECKMANY
/*

Library for the deck of many things.

See the spell script x0_s3_deckmany for an example of
combining these functions to create a deck.

To make your own deck, just add a "Do<whatever>DeckCard" function
for any custom cards you want, then put those cards into the
DoDeckDrawPositive/Negative functions. Then recompile the
spell script x0_s3_deckmany inside your module and a deck inside
your module will use your cards.

*/

// Updated 9_11_08 by 2d2f

#include "x0_i0_treasure"
#include "x0_i0_henchman"
#include "2d2f_includes"

/*************************************************************************
 * CONSTANTS
 *************************************************************************/
const int TOKEN_NAME = 9323;
const int TOKEN_CARD_NAME = 9324;

// This controls how long to delay the actual card effects for
// in order to make the message pop up before it happens
float DECK_DELAY = 6.0;

/*************************************************************************
 * FUNCTION PROTOTYPES
 *************************************************************************/

// Check if the deck has been used before by this creature
int GetHasUsedDeck(object oCaster);

// Mark that the deck has been used by this creature
void SetHasUsedDeck(object oCaster);

// Get the number of draws remaining
int GetNumberDeckDraws(object oCaster);

// Set the number of draws remaining
void SetNumberDeckDraws(object oCaster, int nDraws);

// Do a positive card draw
void DoDeckDrawPositive(object oCaster, int nTurn);

// Do a negative card draw
void DoDeckDrawNegative(object oCaster, int nTurn);

// Get a special deck-specific area if it exists and is available.
// This will start by checking for an area with just the given area
// tag. If that doesn't exist or is taken, it will start looking
// for areas tagged sAreaTag + number, until it finds one that is available.
// X0_DECK_DONJON1, X0_DECK_DONJON2, etc
// Returns OBJECT_INVALID if no area found.
object GetSpecialAreaForDeckCard(string sAreaTag);

// Get a special area and transport the caster (with
// associates but without party members) to the
// X0_DECK_START waypoint inside it.
//
// Returns TRUE on success, FALSE otherwise.
int DoSpecialAreaDeckCard(object oCaster, string sAreaTag, int nTurn);

/*************************************************************************
 * CARD FUNCTIONS
 * If a card draw fails, it will return FALSE, otherwise will return TRUE.
 *************************************************************************/


// ------- NEGATIVE CARDS

// The Fool card (negative)
// Lose 10,000 XP and get 2 extra cards.
int DoFoolDeckCard(object oCaster, int nTurn);

// The Donjon card (negative)
// If a donjon area is available, the caster and associates are transported
// there.
// The area should be tagged X0_DECK_DONJON1.
// The starting location should be tagged X0_DECK_START.
// See the Gauntlet area in module 3 of XP1 as an example.
// (This is a good model to use if you want to create a "Keep" or
// "Void" type card for your own module.)
int DoDonjonDeckCard(object oCaster, int nTurn);

// The Traitor card (negative)
// Change to diametrically-opposed alignment instantly.
int DoTraitorDeckCard(object oCaster, int nTurn);

// The Knave card (negative)
// All non-plot possessions not currently equipped are destroyed.
int DoKnaveDeckCard(object oCaster, int nTurn);

// The Plague card (negative)
// Permanent disease effect applied for duration of the module.
int DoPlagueDeckCard(object oCaster, int nTurn);

// The Looking Glass card (negative)
// Caster's henchman is replaced with an evil doppelganger.
int DoLookingGlassDeckCard(object oCaster, int nTurn);

// The Wyrm card (negative)
// A hostile ancient dragon is lured to the caster.
int DoWyrmDeckCard(object oCaster, int nTurn);


// ------- POSITIVE CARDS

// The Joker card (positive)
// Gain 10,000 XP and get 2 extra cards.
int DoJokerDeckCard(object oCaster, int nTurn);

// The Hoard card (positive)
// Gain 50-100,000 gold instantly
int DoHoardDeckCard(object oCaster, int nTurn);

// The Oracle card (positive)
// Gain permanent premonition effect for duration of the module
int DoOracleDeckCard(object oCaster, int nTurn);

// The Avatar card (positive)
// Caster is transformed into an avatar of their alignment.
int DoAvatarDeckCard(object oCaster, int nTurn);

// The Fountain card (positive)
// All of caster's items are recharged and all stacked items are
// filled up to the maximum possible number.
int DoFountainDeckCard(object oCaster, int nTurn);

// The Hatchling card (positive)
// A wyrmling of alignment-appropriate color appears and follows
// the caster as a summoned creature until damaged, at which point
// it transforms into an adult dragon and fights on the caster's behalf
// until all enemies are slain, then vanishes.
int DoHatchlingDeckCard(object oCaster, int nTurn);

// The Bequest card (positive)
// Gain a major unique magical item (this will respect the
// XP1 treasure system if it is used in the module, otherwise
// random boss-level treasure will be generated).
int DoBequestDeckCard(object oCaster, int nTurn);

/*************************************************************************
 * FUNCTION DEFINITIONS
 *************************************************************************/


// Check if the deck has been used before by this creature
int GetHasUsedDeck(object oCaster)
{
    return GetLocalInt(oCaster, "X0_DECK_USED");
}

// Mark that the deck has been used by this creature
void SetHasUsedDeck(object oCaster)
{
    SetLocalInt(oCaster, "X0_DECK_USED", TRUE);
}

// Get the number of draws remaining
int GetNumberDeckDraws(object oCaster)
{
    return GetLocalInt(oCaster, "X0_DECK_CARDS_LEFT");
}

// Set the number of draws remaining
void SetNumberDeckDraws(object oCaster, int nDraws)
{
    SetLocalInt(oCaster, "X0_DECK_CARDS_LEFT", nDraws);
}

// Do a positive card draw
void DoDeckDrawPositive(object oCaster, int nTurn)
{
    int bDone = FALSE;
    int nTriesMax = 50; // Just as a failsafe
    int nTries = 0;
    string sCardName = "";

    // If a card draw succeeds, bDone will be set to TRUE
    // and this loop will exit.
    while (!bDone && nTries < nTriesMax) {
        nTries++;
        int nCard = Random(5); 

		//SendMessageToPC(GetFirstPC(),"nCard positive: " + IntToString(nCard));
        //DBG_msg("nCard positive: " + IntToString(nCard));

        // For each card, we set the custom token 1 to
        // be the name we want to assign to the card.
        switch (nCard) {
        case 0: bDone = DoJokerDeckCard(oCaster, nTurn);
                sCardName = "The Joker";//GetStringByStrRef(9255); // "Mentor";
                break;
        case 1: bDone = DoHoardDeckCard(oCaster, nTurn);
                sCardName = "The Hoard";//GetStringByStrRef(9258); // "Hoard";
                break;
        case 2: bDone = DoOracleDeckCard(oCaster, nTurn);
                sCardName = "The Oracle";//GetStringByStrRef(9261); //"Oracle";
                break;
        //case 3: bDone = DoAvatarDeckCard(oCaster, nTurn);
               // sCardName = "The Avatar";//GetStringByStrRef(9248); //"Avatar";
                //break;
        case 3: bDone = DoFountainDeckCard(oCaster, nTurn);
                sCardName = "The Fountain";//GetStringByStrRef(9257); //"Fountain";
                break;
        case 4: bDone = DoHatchlingDeckCard(oCaster, nTurn);
                sCardName = "The Hatchling";//GetStringByStrRef(9254); //"Hatchling";
                break;
		//case 6: bDone = DoBequestDeckCard(oCaster, nTurn);
               // sCardName = "The Emperor";//GetStringByStrRef(9249); //"Bequest";
                //break;
        }		
    }

    // Set the caster name and card name as tokens
   // SetCustomToken(TOKEN_NAME, GetName(oCaster));
   // DelayCommand(DECK_DELAY*nTurn - 3.0, SetCustomToken(TOKEN_CARD_NAME, sCardName));

    // Apply the visual effect
	// 2d2f - no visual effect for now
    //int nDeckEffect = 322;
    effect eDraw = EffectVisualEffect(VFX_DUR_DECK_DRAW);
    //DelayCommand(DECK_DELAY * nTurn,
    //             ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
    //                                 eDraw,
    //                                oCaster,6.0));

	 ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
                                     eDraw,
                                     oCaster,6.0);

    if (!bDone)
    {
        // ugh, send error message
        DelayCommand(DECK_DELAY * nTurn - 2.0,
                     FloatingTextStrRefOnCreature(9239, oCaster));
        return;
    }

    // Print out the message
    //DelayCommand(DECK_DELAY * nTurn - 2.0,
                 //FloatingTextStrRefOnCreature(9238, oCaster));
}

// Do a negative card draw
void DoDeckDrawNegative(object oCaster, int nTurn)
{
    int bDone = FALSE;
    int nTriesMax = 50; // Just as a failsafe
    int nTries = 0;
    string sCardName = "";

    // If a card draw succeeds, bDone will be set to TRUE
    // and this loop will exit.
    while (!bDone && nTries < nTriesMax) {
        nTries++;
        int nCard = Random(5);
	//	SendMessageToPC(GetFirstPC(),"nCard negative: " + IntToString(nCard));
        //DBG_msg("nCard negative: " + IntToString(nCard));
        switch (nCard) {
        case 0: bDone = DoFoolDeckCard(oCaster, nTurn);
                sCardName = "The Fool";;//GetStringByStrRef(9256); //"Prince of Lies";
                break;
        //case 1: bDone = DoDonjonDeckCard(oCaster, nTurn);
                //sCardName = GetStringByStrRef(9250); //"Gauntlet";
               // break;
        case 1: bDone = DoTraitorDeckCard(oCaster, nTurn);
                sCardName = "The Traitor";//GetStringByStrRef(9263); //"Traitor";
                break;
        case 2: bDone = DoKnaveDeckCard(oCaster, nTurn);
		        sCardName = "The Knave";//GetStringByStrRef(9259); //"Knave";
                break;
        case 3: bDone = DoPlagueDeckCard(oCaster, nTurn);
                sCardName = "The Black Death";//GetStringByStrRef(9262); //"Plague";
                break;
        //case 4: bDone = DoLookingGlassDeckCard(oCaster, nTurn);
               // sCardName = "The Looking Glass";//GetStringByStrRef(9260); //"Looking Glass";
               // break;
        case 4: bDone = DoWyrmDeckCard(oCaster, nTurn);
                sCardName = "The Wyrm";//GetStringByStrRef(9264); //"Wyrm";
                break;
			
        }	
    }

    // Set the caster name and card name as tokens
    //SetCustomToken(TOKEN_NAME, GetName(oCaster));
    //DelayCommand(DECK_DELAY*nTurn - 3.0, SetCustomToken(TOKEN_CARD_NAME, sCardName));


    // Apply the visual effect
    int nDeckEffect = 322;
    effect eDraw = EffectVisualEffect(VFX_DUR_DECK_DRAW);
    DelayCommand(DECK_DELAY * nTurn,
                 ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
                                     eDraw,
                                     oCaster,6.0));


    if (!bDone) {
        // ugh, send error message
        DelayCommand(DECK_DELAY * nTurn - 2.0,
                    FloatingTextStrRefOnCreature(9239, oCaster));
        return;
    }

    // Print out the message
    //DelayCommand(DECK_DELAY * nTurn - 2.0,
                 //FloatingTextStrRefOnCreature(9238, oCaster));
}



// Get a special deck-specific area if it exists and is available.
// This will start by checking for an area with just the given area
// tag. If that doesn't exist or is taken, it will start looking
// for areas tagged sAreaTag + number, until it finds one that is available.
// X0_DECK_DONJON1, X0_DECK_DONJON2, etc
// Returns OBJECT_INVALID if no area found.
object GetSpecialAreaForDeck(string sAreaTag)
{
    object oArea = GetObjectByTag(sAreaTag);
    if (GetIsObjectValid(oArea) && !GetLocalInt(oArea, "X0_DECK_USED")) {
        SetLocalInt(oArea, "X0_DECK_USED", TRUE);
        return oArea;
    }

    // We didn't find one with the base tag, so start tacking on
    // numbers.
    int nNth = 1;
    oArea = GetObjectByTag(sAreaTag + IntToString(nNth));
    while (GetIsObjectValid(oArea) && GetLocalInt(oArea, "X0_DECK_USED")) {
        nNth++;
        oArea = GetObjectByTag(sAreaTag + IntToString(nNth));
    }

    if (GetIsObjectValid(oArea))
        SetLocalInt(oArea, "X0_DECK_USED", TRUE);

    // Valid or not, return it
    return oArea;
}


// Get a special area and transport the caster (with
// associates but without party members) to the
// X0_DECK_START waypoint inside it.
//
// Returns TRUE on success, FALSE otherwise.
int DoSpecialAreaDeckCard(object oCaster, string sAreaTag, int nTurn)
{
    object oArea = GetSpecialAreaForDeck(sAreaTag);
    if (!GetIsObjectValid(oArea)) return FALSE;

    // We have an area, find the X0_DECK_START waypoint inside it
    object oWay;
    object oTmp = GetFirstObjectInArea(oArea);
    if (GetTag(oTmp) == "X0_DECK_START")
    oWay = oTmp;
    else
    oWay = GetNearestObjectByTag("X0_DECK_START", oTmp);

    if (!GetIsObjectValid(oWay)) return FALSE;
    DelayCommand(DECK_DELAY * nTurn, TransportToWaypoint(oCaster, oWay));
    return TRUE;
}


// The Fool card (negative)
// Lose 10,000 XP and get 2 extra cards.
int DoFoolDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_FOOL_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_FOOL_CARD", TRUE);

    int nXP = GetXP(oCaster);
	int nFinalXP;
	
	if(nXP < 1000){ nFinalXP = 0; } // level 1
	else if (nXP>=1000 && nXP<3000){ nFinalXP = 500; } //level 2
	else if (nXP>=2000 && nXP<6000){ nFinalXP = 2000; } //level 3
	else if (nXP>=6000 && nXP<10000){ nFinalXP = 4000; } //level 4
	else if (nXP>=10000 && nXP<15000){ nFinalXP = 8000; } //level 5
	else if (nXP>=15000 && nXP<21000){ nFinalXP = 12000; } //level 6
	else if (nXP>=21000 && nXP<28000){ nFinalXP = 18000; } //level 7
	else if (nXP>=28000 && nXP<36000){ nFinalXP = 24500; } //level 8
	else if (nXP>=36000 && nXP<45000){ nFinalXP = 32000; } //level 9
	else if (nXP>=45000 && nXP<55000){ nFinalXP = 40500; } //level 10
	else if (nXP>=55000 && nXP<66000){ nFinalXP = 50000; } //level 11
	else if (nXP>=66000 && nXP<78000){ nFinalXP = 60500; } //level 12
	else if (nXP>=78000 && nXP<91000){ nFinalXP = 72000; } //level 13
	else if (nXP>=91000 && nXP<105000){ nFinalXP = 84500; } //level 14
	else if (nXP>=105000 && nXP<120000){ nFinalXP = 98000; } //level 15
	else if (nXP>=120000 && nXP<136000){ nFinalXP = 112500; } //level 16
	else if (nXP>=136000 && nXP<153000){ nFinalXP = 128000; } //level 17
	else if (nXP>=153000 && nXP<171000){ nFinalXP = 144500; } //level 18
	else if (nXP>=171000 && nXP<190000){ nFinalXP = 162500; } //level 19
	else if (nXP>=190000 && nXP<210000){ nFinalXP = 180500; } //level 20
	else if (nXP>=210000 && nXP<231000){ nFinalXP = 200000; } //level 21
	else if (nXP>=231000 && nXP<253000){ nFinalXP = 220500; } //level 22
	else if (nXP>=253000 && nXP<276000){ nFinalXP = 242000; } //level 23
	else if (nXP>=276000 && nXP<300000){ nFinalXP = 264500; } //level 24
	else if (nXP>=300000 && nXP<325000){ nFinalXP = 289000; } //level 25
	else if (nXP>=325000 && nXP<351000){ nFinalXP = 312500; } //level 26
	else if (nXP>=351000 && nXP<378000){ nFinalXP = 338000; } //level 27
	else if (nXP>=378000 && nXP<406000){ nFinalXP = 364500; } //level 28
	else if (nXP>=406000 && nXP<435000){ nFinalXP = 392000; } //level 29
	else{ nFinalXP = nXP - 28000; } //level 30 +
		
	
    DelayCommand(DECK_DELAY * nTurn, SetXP(oCaster, nFinalXP));
    //int nCards = GetLocalInt(oCaster, "X0_DECK_CARDS_LEFT");
	//nCards++;
    //string sMess = GetStringByStrRef(40562);
   // DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Fool.  Another card is automatically drawn."));
    DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Fool."));
   	//SetLocalInt(oCaster, "X0_DECK_CARDS_LEFT", nCards);
    return TRUE;
}

// The Donjon card (negative)
// If a donjon area is available, the caster and associates are transported
// there.
// The area should be tagged X0_DECK_DONJON1.
// The starting location should be tagged X0_DECK_START.
// See the Gauntlet area in module 3 of XP1 as an example.
// (This is a good model to use if you want to create a "Keep" or
// "Void" type card for your own module.)
int DoDonjonDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_DONJON_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_DONJON_CARD", TRUE);

    int nSucc = DoSpecialAreaDeckCard(oCaster, "X0_DECK_DONJON", nTurn);
    if (nSucc) {
        // don't get to draw any more cards!
        SetNumberDeckDraws(oCaster, 0);
        string sMessage = GetStringByStrRef(9247);
        //string sMessage = "The remaining cards vanish from your hands!";
        SendMessageToPC(oCaster, sMessage);
    }


    return nSucc;
}

// The Traitor card (negative)
// Change to diametrically-opposed alignment instantly.
int DoTraitorDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_TRAITOR_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_TRAITOR_CARD", TRUE);

    DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Traitor."));
    

    int nGoodEvil = GetAlignmentGoodEvil(oCaster);
    int nLawChaos = GetAlignmentLawChaos(oCaster);
    if (nGoodEvil == ALIGNMENT_GOOD
        || (nGoodEvil == ALIGNMENT_NEUTRAL && Random(2)) ) {
        // make evil
        DelayCommand(DECK_DELAY * nTurn,
                 AdjustAlignment(oCaster, ALIGNMENT_EVIL, 100));
    } else {
        // make good
        DelayCommand(DECK_DELAY * nTurn,
                 AdjustAlignment(oCaster, ALIGNMENT_GOOD, 100));
    }

    if (nLawChaos == ALIGNMENT_LAWFUL
        || (nLawChaos == ALIGNMENT_NEUTRAL && Random(2)) ) {
        // make chaotic
        DelayCommand(DECK_DELAY * nTurn,
                 AdjustAlignment(oCaster, ALIGNMENT_CHAOTIC, 100));
    } else {
        // make lawful
        DelayCommand(DECK_DELAY * nTurn,
                 AdjustAlignment(oCaster, ALIGNMENT_LAWFUL, 100));
    }

    return TRUE;
}

// The Knave card (negative)
// All non-plot possessions not currently equipped are destroyed.
int DoKnaveDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_KNAVE_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_KNAVE_CARD", TRUE);
    DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Knave."));
    
    object oItem = GetFirstItemInInventory(oCaster);
    while (GetIsObjectValid(oItem)) {
        if (!GetPlotFlag(oItem)) {
            DestroyObject(oItem, DECK_DELAY * nTurn);
        }
        oItem = GetNextItemInInventory(oCaster);
    }
    return TRUE;
}

// Private function used to apply the initial plague effect
void DoPlagueDeckCardEffect(object oCaster)
{
    effect eImp = EffectVisualEffect(VFX_IMP_DISEASE_S);
    ApplyEffectToObject(DURATION_TYPE_INSTANT,
                        eImp,
                        oCaster);

    // Apply damage
    int nDam = d10() + 10;
    if (nDam > GetCurrentHitPoints(oCaster)) {
        nDam = GetCurrentHitPoints(oCaster) - 1;
    }
    effect eDam = EffectDamage(nDam,
                   DAMAGE_TYPE_MAGICAL,
                   DAMAGE_POWER_PLUS_FIVE);

    ApplyEffectToObject(DURATION_TYPE_INSTANT,
                        eDam,
                        oCaster);
}

// The Plague card (negative)
// Permanent disease effect applied for duration of the module.
int DoPlagueDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_PLAGUE_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_PLAGUE_CARD", TRUE);

	DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Black Death."));
    
    // Create the plague object, which will keep applying the
    // nasty plague permanently, even after a restoration spell,
    // muahaha ha ha.... cough, cough.
    object oPlague = CreateObject(OBJECT_TYPE_PLACEABLE,
                  "x0_deck_plague",
                  GetLocation(oCaster));

    if (!GetIsObjectValid(oPlague)) return FALSE;

    SetLocalObject(oPlague, "X0_DECK_TARGET", oCaster);

    DelayCommand(DECK_DELAY * nTurn,
                 AssignCommand(oPlague, DoPlagueDeckCardEffect(oCaster)));

    return TRUE;
}
// Private function to run the actual henchman change after a delay
void DoLookingGlassDeckCardEffect(object oCaster, object oHench)
{
    effect eReplace = EffectVisualEffect(VFX_IMP_REDUCE_ABILITY_SCORE);
    ApplyEffectToObject(DURATION_TYPE_INSTANT, eReplace, oHench);

    FireHenchman(oCaster, oHench);
    ChangeToStandardFaction(oHench, STANDARD_FACTION_HOSTILE);
    DelayCommand(1.0, AssignCommand(oHench, DetermineCombatRound(oCaster)));
}

// The Looking Glass card (negative)
// Caster's henchman is turned hostile.
int DoLookingGlassDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_LOOKGLASS_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_LOOKGLASS_CARD", TRUE);

    object oHench = GetHenchman(oCaster);
    if (!GetIsObjectValid(oHench) || GetArea(oHench) != GetArea(oCaster))
    return FALSE;

    DelayCommand(DECK_DELAY * nTurn,
                 DoLookingGlassDeckCardEffect(oCaster, oHench));
    return TRUE;
}

// Private function to run the actual wyrm summon after a delay
void DoWyrmDeckCardEffect(object oCaster, string sResRef)
{
    object oDrag = CreateObject(OBJECT_TYPE_CREATURE,
                sResRef,
                GetLocation(oCaster),
                TRUE);
    SetIsTemporaryEnemy(oCaster, oDrag);
    DelayCommand(1.0, AssignCommand(oDrag, DetermineCombatRound(oCaster)));
}

// The Wyrm card (negative)
// A dragon is lured to the caster and attacks
int DoWyrmDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_WYRM_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_WYRM_CARD", TRUE);

    int nGoodEvil = GetAlignmentGoodEvil(oCaster);
    string sResRef;
	
	sResRef = "c_reddragon";
	
	
	
	
	
	
	
    /*if (nGoodEvil == ALIGNMENT_EVIL) {
        sResRef = "nw_drgsilv001";
        if (Random(2))
            sResRef = "nw_drggold001";
    } else {
        sResRef = "nw_drgblue001";
        if (Random(2))
            sResRef = "nw_drgred001";
    }*/

    DelayCommand(DECK_DELAY * nTurn,
                 DoWyrmDeckCardEffect(oCaster, sResRef));
                 
    DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Wyrm."));
    

    return TRUE;
}


// ------- POSITIVE CARDS

// The Joker card (positive)
// Gain 10,000 XP and get 2 extra cards.
int DoJokerDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_JOKER_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_JOKER_CARD", TRUE);
	
	int nXP = GetXP(oCaster);
	int nFinalXP;
	
	if(nXP	<	1000){	nFinalXP	=	2000;	}	//	level	1	
	else	if	(nXP>=1000	&&	nXP<3000){	nFinalXP	=	4000;	}	//level	2
	else	if	(nXP>=2000	&&	nXP<6000){	nFinalXP	=	8000;	}	//level	3
	else	if	(nXP>=6000	&&	nXP<10000){	nFinalXP	=	12000;	}	//level	4
	else	if	(nXP>=10000	&&	nXP<15000){	nFinalXP	=	18000;	}	//level	5
	else	if	(nXP>=15000	&&	nXP<21000){	nFinalXP	=	24500;	}	//level	6
	else	if	(nXP>=21000	&&	nXP<28000){	nFinalXP	=	32000;	}	//level	7
	else	if	(nXP>=28000	&&	nXP<36000){	nFinalXP	=	40500;	}	//level	8
	else	if	(nXP>=36000	&&	nXP<45000){	nFinalXP	=	50000;	}	//level	9
	else	if	(nXP>=45000	&&	nXP<55000){	nFinalXP	=	60500;	}	//level	10
	else	if	(nXP>=55000	&&	nXP<66000){	nFinalXP	=	72000;	}	//level	11
	else	if	(nXP>=66000	&&	nXP<78000){	nFinalXP	=	84500;	}	//level	12
	else	if	(nXP>=78000	&&	nXP<91000){	nFinalXP	=	98000;	}	//level	13
	else	if	(nXP>=91000	&&	nXP<105000){	nFinalXP	=	112500;	}	//level	14
	else	if	(nXP>=105000	&&	nXP<120000){	nFinalXP	=	128000;	}	//level	15
	else	if	(nXP>=120000	&&	nXP<136000){	nFinalXP	=	144500;	}	//level	16
	else	if	(nXP>=136000	&&	nXP<153000){	nFinalXP	=	162500;	}	//level	17
	else	if	(nXP>=153000	&&	nXP<171000){	nFinalXP	=	180500;	}	//level	18
	else	if	(nXP>=171000	&&	nXP<190000){	nFinalXP	=	200000;	}	//level	19
	else	if	(nXP>=190000	&&	nXP<210000){	nFinalXP	=	220500;	}	//level	20
	else	if	(nXP>=210000	&&	nXP<231000){	nFinalXP	=	242000;	}	//level	21
	else	if	(nXP>=231000	&&	nXP<253000){	nFinalXP	=	264500;	}	//level	22
	else	if	(nXP>=253000	&&	nXP<276000){	nFinalXP	=	289000;	}	//level	23
	else	if	(nXP>=276000	&&	nXP<300000){	nFinalXP	=	312500;	}	//level	24
	else	if	(nXP>=300000	&&	nXP<325000){	nFinalXP	=	338000;	}	//level	25
	else	if	(nXP>=325000	&&	nXP<351000){	nFinalXP	=	364500;	}	//level	26
	else	if	(nXP>=351000	&&	nXP<378000){	nFinalXP	=	392000;	}	//level	27
	else	if	(nXP>=378000	&&	nXP<406000){	nFinalXP	=	420500;	}	//level	28
	else	if	(nXP>=406000	&&	nXP<435000){	nFinalXP	=	465000;	}	//level	29
	else{	nFinalXP	=	nXP	+	28000;	}	//level	30	+	


    DelayCommand(DECK_DELAY * nTurn, SetXP(oCaster, nFinalXP));
    //int nCards = GetLocalInt(oCaster, "X0_DECK_CARDS_LEFT");

        //string sMess = GetStringByStrRef(40562);
   // SendMessageToPC(oCaster, "You have drawn The Joker.  Another card is automatically drawn.");
	SendMessageToPC(oCaster, "You have drawn The Joker.");
	
	//nCards++;

    //SetLocalInt(oCaster, "X0_DECK_CARDS_LEFT", nCards);
    return TRUE;
}

// The Hoard card (positive)
// Gain 50,000 gold instantly
int DoHoardDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_HOARD_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_HOARD_CARD", TRUE);
    DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Hoard."));
    
	int nRand = Random(4) * 50000;
	
    DelayCommand(DECK_DELAY * nTurn, GiveGoldToCreature(oCaster, 100000 + nRand));
    return TRUE;
}

// The Oracle card (positive)
// Gain permanent premonition effect for duration of the module
int DoOracleDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_ORACLE_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_ORACLE_CARD", TRUE);
	
	DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Oracle."));
    
	
    // Create the oracle object, which will keep applying the
    // oracle effect permanently, even after resting.
    object oOracle = CreateObject(OBJECT_TYPE_PLACEABLE,
                                  "x0_deck_oracle",
                                  GetLocation(oCaster));

    if (!GetIsObjectValid(oOracle))
        return FALSE;

    SetLocalObject(oOracle, "X0_DECK_TARGET", oCaster);

    effect ePrem = EffectDamageReduction(15, DAMAGE_POWER_PLUS_FIVE, 0);
    effect eVis = EffectVisualEffect(VFX_DUR_PROT_PREMONITION);

    //Link the visual and the damage reduction effect
    effect eLink = EffectLinkEffects(ePrem, eVis);

    DelayCommand(DECK_DELAY * nTurn,
         ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oCaster));
    return TRUE;
}

// Private function to create the avatar item on the caster
void DoAvatarDeckCardEffect(object oCaster)
{
    CreateItemOnObject("x0_deck_avatar", oCaster);
}

// Private function to do the avatar transformation effect
void DoAvatarDeckCardTransform(object oCaster)
{
    int nGoodEvil = GetAlignmentGoodEvil(oCaster);
    int nGender = GetGender(oCaster);

    effect ePoly;
    int nVFX;

    // Temporary vars here to avoid magic numbers
    // replace with POLYMORPH_TYPE constants when added to nwscript
    if (nGoodEvil == ALIGNMENT_GOOD) {
        // transform into celestial avenger
        nVFX = VFX_IMP_MAGIC_PROTECTION;
        ePoly = EffectPolymorph(POLYMORPH_TYPE_CELESTIAL_AVENGER);
    } else if (nGoodEvil == ALIGNMENT_EVIL) {
        // transform into vrock or succubus
        nVFX = VFX_IMP_REDUCE_ABILITY_SCORE;
        if (nGender == GENDER_MALE)
            ePoly = EffectPolymorph(POLYMORPH_TYPE_VROCK);
        else
            ePoly = EffectPolymorph(POLYMORPH_TYPE_SUCCUBUS);
    } else {
        // transform into fire or water elemental
        if (nGender == GENDER_MALE) {
            ePoly = EffectPolymorph(POLYMORPH_TYPE_ELDER_FIRE_ELEMENTAL);
            nVFX = VFX_IMP_FLAME_M;
        } else {
            ePoly = EffectPolymorph(POLYMORPH_TYPE_ELDER_WATER_ELEMENTAL);
            nVFX = VFX_IMP_MAGIC_PROTECTION;
        }
    }

    effect eVis = EffectVisualEffect(nVFX);

    SetCustomToken(TOKEN_NAME, GetName(oCaster));
    FloatingTextStrRefOnCreature(9246, oCaster);
    //FloatingTextStringOnCreature(GetName(oCaster)
    //                             + " transforms into an avatar.",
    //                             oCaster);

    ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oCaster);
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oCaster);
}

// The Avatar card (positive)
// Caster is transformed into an avatar of their alignment.
int DoAvatarDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_AVATAR_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_AVATAR_CARD", TRUE);

    // Create the avatar object, which will allow the user
    // to become the avatar at will.
    DelayCommand(DECK_DELAY * nTurn, DoAvatarDeckCardEffect(oCaster));
    DelayCommand(DECK_DELAY * nTurn, DoAvatarDeckCardTransform(oCaster));

    return TRUE;
}

// The Fountain card (positive)
// All of caster's items are recharged and all stacked items are
// filled up to the maximum possible number.
int DoFountainDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_FOUNTAIN_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_FOUNTAIN_CARD", TRUE);
    DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Fountain."));
    
    object oItem = GetFirstItemInInventory(oCaster);
    while (GetIsObjectValid(oItem)) {
        if (!GetPlotFlag(oItem)) {
            // Set maximum charges & stack
            DelayCommand(DECK_DELAY * nTurn, SetItemCharges(oItem, 50));
            DelayCommand(DECK_DELAY * nTurn, SetItemStackSize(oItem, 99));
        }
        oItem = GetNextItemInInventory(oCaster);
    }
    return TRUE;
}


void DoAdultDragonDeckCardRecord(string sTag,object oTarget)
{
    object oRedDragon = GetNearestObjectByTag(sTag);
    SetLocalObject(oTarget, "oRedDragon", oRedDragon);
}


// Private function used to create the hatchling-summoning object
void DoHatchlingDeckCardEffect(object oCaster)
{
    object oHatchObject = CreateObject(OBJECT_TYPE_PLACEABLE,
                                       "x0_deck_hatch",
                                       GetLocation(oCaster));

    SetLocalObject(oHatchObject, "X0_DECK_TARGET", oCaster);
    SetLocalObject(oCaster, "X0_DECK_HATCH_OBJECT", oHatchObject);
}

// Private function used to record the hatchling object
void DoHatchlingDeckCardRecord(string sTag)
{
    object oHatch = GetNearestObjectByTag(sTag);
    SetLocalObject(OBJECT_SELF, "X0_DECK_HATCH", oHatch);

    //DBG_msg("Hatchling summoned: " + GetTag(oHatch));
}


// Private function -- this is assigned to the caster as an action
// to cause them to summon the hatchling.
void DoHatchlingDeckCardSummon()
{
    // Summon the hatchling
    //string sResRef;
    //int nGoodEvil = GetAlignmentGoodEvil(OBJECT_SELF);
    //if (nGoodEvil == ALIGNMENT_EVIL) {
    //    sResRef = "X0_HATCH_EVIL";
    //} else {
    //    sResRef = "X0_HATCH_GOOD";
    //}
	 string sResRef = "c_reddragon_hatchling";
    //DBG_msg("Attempting to summon hatchling: " + sResRef);

    effect eSummon = EffectSummonCreature(sResRef,
                                          VFX_IMP_DIVINE_STRIKE_HOLY,
                                          0.5);

    ApplyEffectAtLocation(DURATION_TYPE_PERMANENT,
                          eSummon,
                          GetOppositeLocation(OBJECT_SELF));

    DelayCommand(3.0, DoHatchlingDeckCardRecord(sResRef));
}


// The Hatchling card (positive)
// A wyrmling of alignment-appropriate color appears and follows
// the caster as a summoned creature until damaged, at which point
// it transforms into an adult dragon and fights on the caster's behalf
// until all enemies are slain, then vanishes.
int DoHatchlingDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_HATCHLING_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_HATCHLING_CARD", TRUE);

    // Summon the hatchling
    DelayCommand(DECK_DELAY * nTurn,
                 AssignCommand(oCaster,
                               DoHatchlingDeckCardSummon()));

    // Create the hatchling object, which will resummon
    // the hatchling.
    DelayCommand(DECK_DELAY * nTurn, DoHatchlingDeckCardEffect(oCaster));
	DelayCommand(DECK_DELAY * nTurn, SendMessageToPC(oCaster, "You have drawn The Hatchling."));
    
    return TRUE;
}



// The Bequest card (positive)
// Gain a major unique magical item (this will respect the
// XP1 treasure system if it is used).
int DoBequestDeckCard(object oCaster, int nTurn)
{
    if (GetLocalInt(oCaster, "X0_DECK_BEQUEST_CARD")) return FALSE;
    SetLocalInt(oCaster, "X0_DECK_BEQUEST_CARD", TRUE);

    DelayCommand(DECK_DELAY * nTurn,
         CTG_CreateTreasure(TREASURE_TYPE_UNIQUE, oCaster, oCaster));
    return TRUE;
}

/*  void main() {} /* */