#include "hench_i0_ai"
#include "quest_inc"
#include "nw_i0_plot"

void CastInitialBuffs()
{
    int nLevel = GetHitDice(OBJECT_SELF);
    ClearAllActions();

    //mage buffs
    if (GetLevelByClass(CLASS_TYPE_WIZARD, OBJECT_SELF) != 0)
    {
        if (nLevel <= 2)
        {
            ActionCastSpellAtObject(SPELL_MAGE_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else if (nLevel <= 4)
        {
            ActionCastSpellAtObject(SPELL_MAGE_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_DEATH_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else if (nLevel <= 6)
        {
            ActionCastSpellAtObject(SPELL_MAGE_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_DEATH_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_DISPLACEMENT, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else if (nLevel <= 8)
        {
            ActionCastSpellAtObject(SPELL_MAGE_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_ELEMENTAL_SHIELD, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_IMPROVED_INVISIBILITY, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else
        {
            ActionCastSpellAtObject(SPELL_MAGE_ARMOR, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_MESTILS_ACID_SHEATH, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_IMPROVED_INVISIBILITY, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
    }

    //cleric buffs
    if (GetLevelByClass(CLASS_TYPE_CLERIC, OBJECT_SELF) != 0)
    {
        if (nLevel <= 2)
        {
            ActionCastSpellAtObject(SPELL_ENDURE_ELEMENTS, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_SHIELD_OF_FAITH, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else if (nLevel <= 4)
        {
            ActionCastSpellAtObject(SPELL_RESIST_ELEMENTS, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_SHIELD_OF_FAITH, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else if (nLevel <= 8)
        {
            ActionCastSpellAtObject(SPELL_PROTECTION_FROM_ELEMENTS, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_PRAYER, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
        else
        {
            ActionCastSpellAtObject(SPELL_PROTECTION_FROM_ELEMENTS, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
            ActionCastSpellAtObject(SPELL_BATTLETIDE, OBJECT_SELF, METAMAGIC_ANY, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
        }
    }

    DelayCommand(0.5, ActionDoCommand(HenchDetermineCombatRound()));
}

void StartConversation(object oSpeaker, string sConversation)
{
    ActionStartConversation(oSpeaker, sConversation, FALSE, FALSE);
}

int InitiativeCheck()
{
    object oPC = GetPCSpeaker();

    int nBonus = 0;
    if (GetHasFeat(FEAT_BLOODED, oPC)) nBonus = nBonus + 2;
    if (GetHasFeat(FEAT_THUG, oPC)) nBonus = nBonus + 2;
    if (GetHasFeat(FEAT_IMPROVED_INITIATIVE, oPC)) nBonus = nBonus + 4;
    if (GetHasFeat(FEAT_EPIC_SUPERIOR_INITIATIVE, oPC)) nBonus = nBonus + 4;

    if (d20() + nBonus >= 12) return TRUE;
    return FALSE;
}

void main()
{
    object oPC = GetPCSpeaker();
    string sDB = CharacterDB(oPC);

    //Just a precaution not to have it accidentally launched multiple times
    if (GetLocalInt(OBJECT_SELF, "ConvCancel") == TRUE) return;
    else
        {
        SetLocalInt(OBJECT_SELF, "ConvCancel", TRUE);
        DelayCommand(0.5, DeleteLocalInt(OBJECT_SELF, "ConvCancel"));
        }

    //If the NPC is an adventurer that wants to kill us
    if (GetLocalInt(OBJECT_SELF, "Adventurer") == TRUE && GetLocalInt(OBJECT_SELF, "WillAttack") == 1)
    {
        SetIsTemporaryEnemy(oPC, OBJECT_SELF);
        SetPlotFlag(OBJECT_SELF, FALSE);
        CastInitialBuffs();
        //HenchDetermineCombatRound();
    }

    //If the NPC is a nemesis
    if (GetLocalInt(OBJECT_SELF, "Nemesis") == TRUE)
    {
        effect eEffect = GetFirstEffect(oPC);
        while (GetIsEffectValid(eEffect))
        {
            if (GetEffectCreator(eEffect) == OBJECT_SELF) RemoveEffect(oPC, eEffect);
            eEffect = GetNextEffect(oPC);
        }

        SetIsTemporaryEnemy(oPC, OBJECT_SELF);
        SetPlotFlag(OBJECT_SELF, FALSE);
        if (Random(2) == 0) SetLocalInt(OBJECT_SELF, "WillRun", TRUE);
        CastInitialBuffs();
        //HenchDetermineCombatRound();
    }

    //If the quest target is successfully kidnapped and is going to be escorted by hirelings
    object oEscort;
    if (GetLocalInt(OBJECT_SELF, "KidnapTarget") == TRUE && GetLocalInt(OBJECT_SELF, "Kidnapped") == TRUE)
    {
        AddRandomQuestJournalEntry(oPC, 2);

        oEscort = CreateObject(OBJECT_TYPE_CREATURE, "anc_kidnap_escor", GetLocation(OBJECT_SELF), FALSE);
        AssignCommand(oEscort, ClearAllActions());
        AssignCommand(oEscort, StartConversation(oPC, "hireling"));
        AssignCommand(oEscort, EscapeArea(FALSE));
        DelayCommand(25.0, DestroyObject(oEscort));
        //SetCommandable(FALSE, oEscort);

        oEscort = CreateObject(OBJECT_TYPE_CREATURE, "anc_kidnap_escor", GetLocation(OBJECT_SELF), FALSE);
        AssignCommand(oEscort, ClearAllActions());
        AssignCommand(oEscort, EscapeArea(FALSE));
        DelayCommand(25.0, DestroyObject(oEscort));
        //SetCommandable(FALSE, oEscort);

        AssignCommand(OBJECT_SELF, ClearAllActions());
        AssignCommand(OBJECT_SELF, EscapeArea(FALSE));
        DelayCommand(25.0, DestroyObject(OBJECT_SELF));
        //SetCommandable(FALSE, OBJECT_SELF);
    }

    //If the quest target is going to attack
    if (GetLocalInt(OBJECT_SELF, "Quest_Attack") == TRUE)
    {
        if (GetLocalInt(OBJECT_SELF, "Kidnapper") == TRUE)
        {
            //Find the kidnapped NPC
            object oKidnapped = GetFirstObjectInArea(GetArea(OBJECT_SELF));
            while (oKidnapped != OBJECT_INVALID)
            {
                if (GetLocalInt(oKidnapped, "RansomQuest") == TRUE) break;
                oKidnapped = GetNextObjectInArea(GetArea(OBJECT_SELF));
            }

            if (InitiativeCheck() == TRUE)
            {
                SetLocalInt(oKidnapped, "Rescued", TRUE);
            }
            else
            {
                SetPlotFlag(oKidnapped, FALSE);
                ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oKidnapped);
                AddRandomQuestJournalEntry(oPC, 3);
                switch (Random(3))
                {
                    case 0: AssignCommand(OBJECT_SELF, SpeakString("Bad move!")); break;
                    case 1: AssignCommand(OBJECT_SELF, SpeakString("The blood is on your hands!")); break;
                    case 2: AssignCommand(OBJECT_SELF, SpeakString("This death was not necessary!")); break;
                }
            }
        }

        if (GetLocalInt(OBJECT_SELF, "BeganAttacking") == FALSE && (GetCampaignString(sDB, "QUEST_TEMPLATE") == "interrogate" || GetCampaignString(sDB, "QUEST_TEMPLATE") == "kill") && GetCampaignInt(sDB, "QUEST_COMPLICATION") == 2) //add conditions for quest types (kill, interrogate...)
        {
        SetLocalInt(OBJECT_SELF, "BeganAttacking", TRUE);
        string sAreaString = GetLocalString(GetArea(OBJECT_SELF), "AreaString");
        string sRace = GetCampaignString(sDB, "QUEST_NPC_RACE");
        object oWaypoint = GetWaypointByTag("event_wp_"+sAreaString+"_2");
        location lLocation = GetLocation(oWaypoint);
        object oMob1 = CreateObject(OBJECT_TYPE_CREATURE, "quest_bguard_"+sRace, lLocation);

        oWaypoint = GetWaypointByTag("event_wp_"+sAreaString+"_3");
        lLocation = GetLocation(oWaypoint);
        object oMob2 = CreateObject(OBJECT_TYPE_CREATURE, "quest_bguard_"+sRace, lLocation);

        LevelHenchmanUpTo(oMob1, GetHitDice(oPC)-3, CLASS_TYPE_INVALID, 0, GetCreatureStartingPackage(oMob1), PACKAGE_INVALID);
        LevelHenchmanUpTo(oMob2, GetHitDice(oPC)-3, CLASS_TYPE_INVALID, 0, GetCreatureStartingPackage(oMob2), PACKAGE_INVALID);

        int nBonus;
        switch (GetHitDice(oPC)-25)
            {
                case 1:
                case 2: nBonus = 1; break;
                case 3:
                case 4: nBonus = 2; break;
                case 5: nBonus = 3; break;
                case 6:
                case 7: nBonus = 4; break;
                case 8:
                case 9: nBonus = 5; break;
                case 10: nBonus = 6; break;
                case 11:
                case 12: nBonus = 7; break;
                case 13:
                case 14: nBonus = 8; break;
                case 15: nBonus = 9; break;
                default: nBonus = 0;
            }

        if (nBonus != 0)
            {
                ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectAttackIncrease(nBonus), oMob1);
                ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectAttackIncrease(nBonus), oMob2);
            }
        }


        SetIsTemporaryEnemy(oPC);
        SetPlotFlag(OBJECT_SELF, FALSE);
        ClearAllActions();
        if (Random(10) == 0 && (GetCampaignInt(sDB, "1_NPC_OCCUPIED") == FALSE || GetCampaignInt(sDB, "2_NPC_OCCUPIED") == FALSE || GetCampaignInt(sDB, "3_NPC_OCCUPIED") == FALSE)) SetLocalInt(OBJECT_SELF, "WillRun", TRUE);
        CastInitialBuffs();
        //HenchDetermineCombatRound();

        object oMob = GetFirstObjectInArea(GetArea(OBJECT_SELF));
        while (GetIsObjectValid(oMob))
        {
            if (GetLocalInt(oMob, "Bodyguard") == TRUE)
            {
                SetIsTemporaryEnemy(oPC, oMob);
                SetPlotFlag(oMob, FALSE);
                AssignCommand(oMob, ClearAllActions());
                AssignCommand(oMob, ActionAttack(oPC));
            }
            oMob = GetNextObjectInArea(GetArea(OBJECT_SELF));
        }
        return;
    }

    //If the quest is halted
    if (GetLocalInt(OBJECT_SELF, "Quest_Halt") == TRUE)
    {
        //If the PC is supposed to kill the NPC
        if (GetCampaignString(sDB, "QUEST_EXTRA2") == "mustkill")
        {
            AddRandomQuestJournalEntry(oPC, 3);
        }

        SetPlotFlag(OBJECT_SELF, TRUE);
        ClearAllActions();
        ActionMoveAwayFromObject(GetPCSpeaker(), FALSE);
        ActionDoCommand(DestroyObject(OBJECT_SELF));

        object oMob = GetFirstObjectInArea(GetArea(OBJECT_SELF));
        while (GetIsObjectValid(oMob))
        {
            if (GetLocalInt(oMob, "Bodyguard") == TRUE)
            {
                SetPlotFlag(oMob, TRUE);
                AssignCommand(oMob, ClearAllActions());
                AssignCommand(oMob, ActionMoveAwayFromObject(GetPCSpeaker(), FALSE));
                AssignCommand(oMob, ActionDoCommand(DestroyObject(oMob)));
            }
            oMob = GetNextObjectInArea(GetArea(OBJECT_SELF));
        }
    }

}