summaryrefslogblamecommitdiff
path: root/npc/042-5/ctrl.txt
blob: e36eeb5cef1dcc934e5dd4f519953feaa421a01e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                                              
                                                    













                                                                           

                                           

                       

                                                                                              

                     

                                                                                      
                  
                                                                                        
                  
                                                                                        








                                                  
                                                   


                  
                                       
                   






                                                                             
                                                      














































                                                                                                      











                                                               
                                       

















                                                      
                                                                            

                       
                                              

                               
                                                 
                                                                                           


                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

 
                                                           
                                                                         















                                                                        





















                                                                                     


                                                                             
                                                        






                                                                    
                                                                                                                                                                                                                                                                   

























                                                                                        



 
 
// TMW 2 Script
// Author:
//  Jesusalva
//  Micksha
// Description:
//  Controls sewers.
//  FIXME: The warps back should only work if treasure was found
//  Spawn monsters and respawns them.

// A simple random treasure chest - to be sure players were introduced to this
// awesome system. Same rules as any treasure box still applies.
042-5,0,0,0	script	#ctrl0425	NPC_HIDDEN,{
    function monster0425;
    end;

OnInstanceInit:
    // Yes, we just hope it works out of box
    explode(.@map$, .map$, "@");
    .@g=atoi(.@map$[1]);
    if (.@g < 1) {
        debugmes "[ERROR] [KAMELOT] Unable to spawn for Kamelot %s", .map$;
        debugmes "[ERROR] [KAMELOT] Using dummy data (returned: %d)", .@g;
        .@g=0;
    }
    debugmes "Spawning monsters for guild %d", .@g;
    .@mx=getguildavg(.@g);
    monster0425(4, 35, 20,  60, 100, .@mx);
    monster0425(4, 20, 20,  35, 100, .@mx);

    // Neutral monsters
    areamonster(.map$, 35, 20, 60, 100, strmobinfo(1, Blub), Blub, 5);
    areamonster(.map$, 20, 20, 35, 100, strmobinfo(1, ManaGhost), ManaGhost, max(1, .@mx/10));

    // Bonus monsters
    if (!rand2(3))
        areamonster(.map$, 20, 20, 60, 100, strmobinfo(1, WhirlyBird), WhirlyBird, 1);
    if (!rand2(2))
        areamonster(.map$, 20, 20, 60, 100, strmobinfo(1, SilverChest), SilverChest, 1);
    if (!rand2(2))
        areamonster(.map$, 20, 20, 60, 100, strmobinfo(1, BronzeChest), BronzeChest, 2);
    end;

OnKillMob:
    if (!playerattached())
        goto OnRespawn;
    // Maybe a reward is due
    .@g=getcharid(2);
    if (.@g < 1) percentheal -100, -100;
    getexp $KAMELOT_MX[.@g]*7, $KAMELOT_MX[.@g]*3;
    .@delay=max(7000, 42000-$KAMELOT_PC[.@g]*2000);
    // FALLTHROUGH

OnRespawn:
    .@delay=(.@delay ? .@delay : 7000);
    sleep(.@delay);
    // Yes, we just hope it works out of box
    explode(.@map$, .map$, "@");
    .@g=atoi(.@map$[1]);
    if (.@g < 1) {
        debugmes "[ERROR] [KAMELOT] Unable to respawn for Kamelot %s", .map$;
        .@g=0;
    }
    monster0425(1, 20, 20, 80, 120, $KAMELOT_MX[.@g]);
    end;

function monster0425 {
    .@label$=instance_npcname(.name$)+"::OnKillMob";
    .@gcount=getarg(0);
    .@x1=getarg(1);
    .@y1=getarg(2);
    .@x2=getarg(3);
    .@y2=getarg(4);
    .@avg=getarg(5);
    .@m$=instance_mapname("042-5");
    //debugmes "Total %d, map %s (power %d)", .@gcount, .@m$, .@avg;
    freeloop(true);
    for (.@i=0; .@i < .@gcount; .@i++) {
        .@mobId=any(CursedSoldier, CursedArcher); // 50-50 ratio
        .@mob=areamonster(.@m$, .@x1, .@y1, .@x2, .@y2, strmobinfo(1, .@mobId), .@mobId, 1, .@label$);
        // Reconfigure the monster
        setunitdata(.@mob, UDT_LEVEL, .@avg);
        setunitdata(.@mob, UDT_STR, 1+.@avg*5/10);
        setunitdata(.@mob, UDT_AGI, 1+.@avg*4/10);
        setunitdata(.@mob, UDT_VIT, 1+.@avg*5/10);
        setunitdata(.@mob, UDT_INT, 1+.@avg*5/10);
        setunitdata(.@mob, UDT_DEX, 1+.@avg*5/10);
        setunitdata(.@mob, UDT_LUK, 1+.@avg*4/10);
        setunitdata(.@mob, UDT_ADELAY, 1472);
        setunitdata(.@mob, UDT_ATKRANGE, (.@mobId == CursedArcher ? any(6,7) : any(1,2)));
        // Battle Status
        setunitdata(.@mob, UDT_MAXHP,    .@avg*38);
        setunitdata(.@mob, UDT_HP,       .@avg*38);
        setunitdata(.@mob, UDT_ATKMIN,   .@avg*50/10);
        setunitdata(.@mob, UDT_ATKMAX,   .@avg*70/10);
        setunitdata(.@mob, UDT_DEF,      1+.@avg*11/10);
        setunitdata(.@mob, UDT_MDEF,     1+.@avg*7/10);
        setunitdata(.@mob, UDT_HIT,      .@avg*6); // Advised: x3
        setunitdata(.@mob, UDT_FLEE,     .@avg*40/10); // Advised: x4
        // Critical calculation
        .@min=8;
        .@max=max(.@min, min(35, .@avg/4));
        setunitdata(.@mob, UDT_CRIT,     rand2(.@min, .@max));
        // Loop through
    }
    freeloop(false);
    return;
    }

}

///////////////////////////////////////////////////////////////
// This is required for others

// KamelotTreasure( POSITION ID )
function	script	KamelotTreasure	{
    .@id=getarg(0);
    .@g=getcharid(2);
    if (.@g < 1) percentheal -100, -100;
    if ($KAMELOT_KEYMASK[.@g] & .@id) {
        mesc l("The chest is unlocked and empty.");
        close;
    }
    inventoryplace Iten, 1, NPCEyes, 2;

    mesc l("Open the chest?");
    mesc l("Cost: 1 @@", getitemlink(TreasureKey)), 1;
    if (!countitem(TreasureKey))
        close;
    next;
    if (askyesno() == ASK_NO)
        close;

    delitem TreasureKey, 1;
    mesc l("You open the chest!");

    .@empty=($KAMELOT_KEYMASK[.@g] & .@id);
    $KAMELOT_KEYMASK[.@g]=$KAMELOT_KEYMASK[.@g]|.@id;

    if (!.@empty) {
        if (.@id == $KAMELOT_KEY[.@g]) {
            dispbottom l("You found the key!");
            rentitem KamelotKey, 86400; // Ensure they expire after 24 hours
            .@key=true;
        }
        .@r=rand2(10000)-$KAMELOT_MX[.@g]+100;

        // Select treasure list
        if (.@r <= 0) // 0.01% total, 0.025% each
            .@loot=any(MylarinDust, SupremeGift, HousingLetterIII, TimeFlask, MercCard_EH);
        else if (.@r < 300) // 0.3% each
            .@loot=any(MagicApple, PrismGift, EquipmentBlueprintD, ChampionshipBow, Halberd, AncientShield, AncientSword, Setzer, MercBoxD, Shemagh);
        else
            .@loot=any(SacredImmortalityPotion, DivineApple, ArcmageBoxset, GoldenApple, MercBoxA, MercBoxB, MercBoxC, MoveSpeedPotion, AtroposMixture, EverburnPowder, IridiumOre, PlatinumOre, YerbaMate, SmokeGrenade, SnakeEgg, LachesisBrew, BoneAmmoBox, GoldPieces, SilverGift, TerraniteOre, LeadOre, TinOre, SilverOre, GoldOre, TitaniumOre, FluoPowder, EquipmentBlueprintC, AlchemyBlueprintC, AlchemyBlueprintD, AncientBlueprint, JasmineTea, MoubooSteak, ClothoLiquor, Coal, RedPlushWine, HastePotion, CoinBag, StrengthPotion, Pearl, BronzeGift, IronOre, CopperOre, BlueDye, EquipmentBlueprintB, AlchemyBlueprintB, AlchemyBlueprintC, OolongTea, Croconut, CelestiaTea, MoubooSteak, ClothoLiquor, Coal, SmallMushroom, HastePotion, StrengthPotion, WoodenLog, LeatherPatch, DwarvenSake, EquipmentBlueprintA, EquipmentBlueprintB, AlchemyBlueprintA, SpearmintTea, TreasureMap, FatesPotion, CrazyRum, LightGreenDiamond, EarthPowder, WoodenLog, MysteriousBottle, FluoPowder, ChamomileTea); // > 70 options (~1% each)


        mesc l("You find @@ inside!", getitemlink(.@loot));
        // If itemtype == Armor/Weapon, make it guild bound and put bonus
        .@t=getiteminfo(.@loot, ITEMINFO_TYPE);
        if (.@t == IT_WEAPON) {
            getitembound .@loot, 1, 2;
            delinventorylist(); // Needed, because we'll rely on rfind()
            getinventorylist();
            .@index=array_rfind(@inventorylist_id, .@loot);
            setitemoptionbyindex(.@index, 0, IOPT_SPLASHDAMAGE, 1);
        } else if (.@t == IT_ARMOR) {
            getitembound .@loot, 1, 2;
            delinventorylist(); // Needed, because we'll rely on rfind()
            getinventorylist();
            .@index=array_rfind(@inventorylist_id, .@loot);
            setitemoptionbyindex(.@index, 0, ATTR_TOLERACE_ALL, 10);
        } else {
            getitem .@loot, 1;
        }
    } else {
        mesc l("You find @@ inside!", l("nothing"));
        mesc l("Seems like someone else opened this chest before you!");
    }

    // Announcement
    if (.@key)
        .@p$=b(" They found the key!");
    mapannounce "042-6@"+.@g, strcharinfo(0)+" has opened a Treasure Chest!"+.@p$, 0;
    mapannounce "042-7@"+.@g, strcharinfo(0)+" has opened a Treasure Chest!"+.@p$, 0;
    mapannounce "042-8@"+.@g, strcharinfo(0)+" has opened a Treasure Chest!"+.@p$, 0;
    mapannounce "042-9@"+.@g, strcharinfo(0)+" has opened a Treasure Chest!"+.@p$, 0;
    // Guild Master Notification
    .@gm$=getguildmaster(.@g);
    if (!getcharid(3, .@gm$)) return;
    .@gma=getcharid(3, .@gm$);
    .@gmb=getcharid(0, .@gm$);
    if (!isloggedin(.@gma, .@gmb)) return;
    message .@gm$, strcharinfo(0)+" has opened a Treasure Chest."+.@p$;
    return;
}

/////////////////////////////////////////////////////////////////////////////
// KamelotBoss(Map, x, y, power, NPC)
function	script	KamelotBoss	{
    .@label$=instance_npcname(getarg(4))+"::OnKillBoss";
    .@gcount=1;
    .@x1=getarg(1);
    .@y1=getarg(2);
    .@avg=getarg(3);
    .@m$=instance_mapname(getarg(0));
    //debugmes "Total %d, map %s (power %d)", .@gcount, .@m$, .@avg;
    .@mobId=any(CursedSoldier, CursedArcher); // 50-50 ratio
    .@name$=any("Gawain", "Tristan", "Kay", "Palamedes", "Mordred", "Bors", "Bedivere", "Lionel", "Bleoberry", "Lucan", "Lamorak", "Pellas", "Hector", "Dragonet", "Bronor", "Alymere"); // Typos on purpose: https://www.arthurian-legend.com/knights-round-table/
    .@mob=monster(.@m$, .@x1, .@y1, .@name$, .@mobId, 1, .@label$);
    // Reconfigure the monster
    setunitdata(.@mob, UDT_LEVEL, .@avg+20);
    setunitdata(.@mob, UDT_STR, 1+.@avg*7/10);
    setunitdata(.@mob, UDT_AGI, 1+.@avg*5/10);
    setunitdata(.@mob, UDT_VIT, 1+.@avg*7/10);
    setunitdata(.@mob, UDT_INT, 1+.@avg*6/10);
    setunitdata(.@mob, UDT_DEX, 1+.@avg*6/10);
    setunitdata(.@mob, UDT_LUK, 1+.@avg*7/10);
    setunitdata(.@mob, UDT_ADELAY, 1072);
    setunitdata(.@mob, UDT_ATKRANGE, (.@mobId == CursedArcher ? any(7,8) : any(2,2,3)));
    // Battle Status
    setunitdata(.@mob, UDT_MAXHP,    .@avg*450);
    setunitdata(.@mob, UDT_HP,       .@avg*450);
    setunitdata(.@mob, UDT_ATKMIN,   .@avg*60/10);
    setunitdata(.@mob, UDT_ATKMAX,   .@avg*70/10);
    setunitdata(.@mob, UDT_DEF,      1+.@avg*14/10);
    setunitdata(.@mob, UDT_MDEF,     1+.@avg*9/10);
    setunitdata(.@mob, UDT_HIT,      .@avg*16); // Advised: x3
    setunitdata(.@mob, UDT_FLEE,     .@avg*45/10); // Advised: x4
    // Critical calculation
    .@min=30;
    .@max=max(.@min, min(70, .@avg/2));
    setunitdata(.@mob, UDT_CRIT,     rand2(.@min, .@max));
    return;
}