/// /// /// /// /// /// /// /// /// /// /// ///
/// lib_witchgrass
/// This is an include file.
/// TimeStamps are accurate for checking one unit (ie. one hour or one day).
/// I plan to write a compare function for timestamps, that would be accurate
/// for any unit.
/// The other functions are used by the various witchgrass scripts.
///
/// Created by Gilgon Avalrock
/// /// /// /// /// /// /// /// /// /// /// ///

#include "prc_inc_racial"

int ONE_MONTH  = 100000000;
int ONE_DAY    = 1000000;
int ONE_HOUR   = 10000;
int ONE_MINUTE = 100;

//used to store all time info as one integer
//doesn't take year into account
int GetTimeStamp(){
   int month  = GetCalendarMonth();
   int day    = GetCalendarDay();
   int hour   = GetTimeHour();
   int minute = GetTimeMinute();
   int second = GetTimeSecond();

   int timestamp = (month*ONE_MONTH)+(day*ONE_DAY)+(hour*ONE_HOUR)+(minute*ONE_MINUTE)+(second);
   return timestamp;
}

//called whenever a creature inhales witchgrass smoke
int GetHigh(object oSmoker){
    int time = GetTimeStamp();
    int lastsmoke = GetLocalInt(oSmoker,"nMyLastToke");
    float duration = HoursToSeconds(1);//effects last 1 game hour
    string comment;

    //check to see how long since my last smoke
    if(lastsmoke==0 || (time-lastsmoke) > ONE_HOUR){
        //apply effects
        ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectMovementSpeedDecrease(10), oSmoker, duration);
        ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectSkillIncrease(SKILL_SPOT,5), oSmoker, duration);
        ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectSkillIncrease(SKILL_LISTEN,5), oSmoker, duration);
        ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectAbilityIncrease(ABILITY_WISDOM,1), oSmoker, duration);
        ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_INTELLIGENCE,1), oSmoker, duration);
        //I had problems with this visual effect if had been fired off previously...
        if(lastsmoke!=0)
            RemoveEffect( oSmoker, EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED));
        DelayCommand(2.f,ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED), oSmoker, duration));

        SetLocalInt(oSmoker,"nMyLastToke",time);
        //random emotes and side effects
        switch(d6()){
        case 1:
            comment="*cough, cough*";
            break;
        case 2:
            comment="Oh, yeah. This is the good stuff.";
            DelayCommand(3.f,AssignCommand(oSmoker,ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING,1.0f,3.0f)));
            break;
        case 3:
            comment="Woah. Heh, heh. I feel like I'm floating.";
            DelayCommand(3.f,AssignCommand(oSmoker,ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING,1.0f,3.0f)));
            break;
        case 4:
            comment="Um, where was I going?";
            DelayCommand(3.f,ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectConfused(), oSmoker, RoundsToSeconds(d4())));
            break;
        //case 5,6 do nothing
        }
        DelayCommand(2.f,AssignCommand(oSmoker,ActionSpeakString(comment)));
        return 1;
    }else{//it hasn't been long enough, so just slow the smoker down some more.
        ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectMovementSpeedDecrease(10), oSmoker, duration);
        RemoveEffect( oSmoker, EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED));
        DelayCommand(2.f,ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED), oSmoker, duration-2.0f));
        SetLocalInt(oSmoker,"nMyLastToke",time);
        //random emotes and side effects
        switch(d4()){
        case 1:
            comment="I shouldn't smoke so often.";
            break;
        case 2:
            comment="Man, now I just feel tired.";
            DelayCommand(3.f,AssignCommand(oSmoker,ActionPlayAnimation( ANIMATION_LOOPING_SIT_CROSS, 1.0f, 3.f)));
            DelayCommand(4.f,ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectSleep(), oSmoker, RoundsToSeconds(d2())));
            break;
        case 3:
            comment="Too much of a good thing, eh?";
            break;
        case 4:
            comment="I could use a nap.";
            break;
        }
        DelayCommand(2.f,AssignCommand(oSmoker,ActionSpeakString(comment)));
        return 0;
    }
}
//used when the whole plant is burned
int DestroyInventory( object oObject, float fDelay=0.0f ){
    int count = 0;
    if(GetHasInventory(oObject)){
        object oItem = GetFirstItemInInventory(oObject);
        while(oItem != OBJECT_INVALID){
            count++;
            DestroyObject( oItem, fDelay );
            oItem = GetNextItemInInventory(oObject);
        }
    }
    return count;
}
//set plant on fire
void SetOnFire( object oObject ) {
    location lBurnLocation = GetLocation( oObject );
    //burns for 5-7 seconds
    float fBurnDuration = IntToFloat( 8 - d3() );
    string sFireResRef = "plc_flamesmall";

    //destroy inventory and plant
    DestroyInventory(oObject);
    DestroyObject( oObject, fBurnDuration / 2 );

    //create fire effect
    object oFire = CreateObject( OBJECT_TYPE_PLACEABLE, sFireResRef, lBurnLocation );
    DestroyObject( oFire, fBurnDuration );
}

//used when planting a new witchgrass plant
void CreateNewPlant( object oPlanter ){
    AssignCommand(oPlanter,ClearAllActions());
    AssignCommand(oPlanter,ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW,1.0f,2.0f));
    location lLoc = GetLocation(oPlanter);
    vector vPos = GetPositionFromLocation(lLoc);
    vPos = vPos + AngleToVector(GetFacing(oPlanter));
    lLoc = Location(GetAreaFromLocation(lLoc),vPos,GetFacingFromLocation(lLoc));
    object oPlant = CreateObject(OBJECT_TYPE_PLACEABLE, "witchgrass", lLoc, TRUE);
    //random emote
    switch(d6()){
    case 1:
        DelayCommand(3.0f, AssignCommand(oPlanter,ActionSpeakString("That's what I call 'miricle grow'.")));
        break;
    case 2:
        DelayCommand(3.0f, AssignCommand(oPlanter,ActionSpeakString("Grows like a weed.")));
        break;
    case 3:
        DelayCommand(3.0f, AssignCommand(oPlanter,ActionSpeakString("Truly the plant of the gods.")));
        break;
    case 4:
        DelayCommand(3.0f, AssignCommand(oPlanter,ActionSpeakString("Must be magic seeds...")));
        break;
    //case 5,6 do nothing
    }
}

//The following two functions were taken from Jason Robinson from his smokable pipe item.
//The first of which was optimized, and the second of which was trimmed down to just the racial data.
location GetLocationAboveAndInFrontOf(object oTarget, float fDist, float fHeight)
{
    object oArea = GetArea(oTarget);
    vector vPosition = GetPosition(oTarget);
    float fOrientation = GetFacing(oTarget);
    vector vNewPos = AngleToVector(fOrientation);
    float vZ = vPosition.z + fHeight;
    float vX = vPosition.x + fDist * vNewPos.x;
    float vY = vPosition.y + fDist * vNewPos.y;
    vNewPos = Vector(vX, vY, vZ);
    return Location(oArea, vNewPos, fOrientation);
}

location GetSmokeLocation(object oSmoker)
{
    float fHeight = 1.7;
    float fDistance = 0.1;
    // Set height based on race and gender
    if (GetGender(oSmoker) == GENDER_MALE)
    {
        switch (MyPRCGetRacialType(oSmoker))
        {
            case RACIAL_TYPE_HUMAN:
            case RACIAL_TYPE_HALFELF:
                fHeight = 1.7;
                fDistance = 0.12;
                break;

            case RACIAL_TYPE_ELF:
                fHeight = 1.55;
                fDistance = 0.08;
                break;

            case RACIAL_TYPE_GNOME:
            case RACIAL_TYPE_HALFLING:
                fHeight = 1.15;
                fDistance = 0.12;
                break;

            case RACIAL_TYPE_DWARF:
                fHeight = 1.2;
                fDistance = 0.12;
                break;

            case RACIAL_TYPE_HALFORC:
                fHeight = 1.9;
                fDistance = 0.2;
                break;
        }
    }
    else
    {
        // FEMALES
        switch (MyPRCGetRacialType(oSmoker))
        {
            case RACIAL_TYPE_HUMAN:
            case RACIAL_TYPE_HALFELF:
                fHeight = 1.6;
                fDistance = 0.12;
                break;

            case RACIAL_TYPE_ELF:
                fHeight = 1.45;
                fDistance = 0.12;
                break;

            case RACIAL_TYPE_GNOME:
            case RACIAL_TYPE_HALFLING:
                fHeight = 1.1;
                fDistance = 0.075;
                break;

            case RACIAL_TYPE_DWARF:
                fHeight = 1.2;
                fDistance = 0.1;
                break;

            case RACIAL_TYPE_HALFORC:
                fHeight = 1.8;
                fDistance = 0.13;
                break;
        }
    }

    return GetLocationAboveAndInFrontOf(oSmoker, fDistance, fHeight);
}

//uses the above two functions to create smoke by a player's face, or out of an object.
void GenerateSmoke(object oSmoker, int bPlayer = FALSE){
    location lLoc;
    if(bPlayer){
        //find the location in front of the players mouth...
        lLoc = GetSmokeLocation(oSmoker);
    }else{
        //object...just use its location
        lLoc = GetLocation(oSmoker);
    }
    //generate smoke
    ApplyEffectAtLocation(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_SMOKE_PUFF),lLoc);
}

//::void main(){}