Generic Gachapon NPC

Results 1 to 10 of 10
  1. #1
    desk.getCoffee().drink(); AngelSpirit is offline
    MemberRank
    Jul 2010 Join Date
    CanadaLocation
    318Posts

    Generic Gachapon NPC

    Merry Christmas, RZ.

    I built this Gachapon script a while ago with the express intent of replacing all the terrible, poorly coded Gachapon scripts currently used. This Gachapon was made to support all kinds of extras, such as:
    • Displaying the list of rewards
    • Displaying the chance of each reward, in percent
    • Gaining any quantity of any item
    • A pretty, formatted UI
    • Using weighted chances instead of having the same chance for each item
    • Easily customizable
    • Does not require any new functions to be added to the source (Well, probably. I can't account for every source out there, but I tried to use only functions that were common to many sources.)

    Here's a sample screenshot. I only have one screenshot, because lazy:


    And here's the code. There may be a fencepost error in the way the probability is calculated, I haven't checked. Just know that the chances displayed in the NPC might not always add up to exactly 100%, though it should be very, very close.
    PHP Code:
    /*
            NPC Name:               Gachapon (Generic)
            Author:                 AngelSpirit
            Description:            Multi-purpose Gachapon NPC, built to be easily editable and adaptable.
    */
    importPackage(java.util);
    importPackage(Packages.client.inventory);
    importPackage(Packages.server);

    //Constants -- change these to suit your needs

    //Set to false to disable this NPC.
    var enabled true;

    //Whether or not to allow players to view the list of rewards.  Note that GM's may always see the reward list, regardless of this setting.
    var showRewards false;

    //Whether or not to show the individual chances of obtaining items.  Only useful if "showRewards" is set to true.
    var showRewardChances true;

    //Rewards, listed as (ItemID, Quantity, Weight).  Weights are relative, and do not have to add up to 100.
    var rewards = Array(
        
    1302000,1,20,
        
    1302001,1,30,
        
    4050000,7,70
    );

    Constants = {
        
    //ItemID to use as the "ticket"
        
    Ticket 5220010,
        
    //Number of free inventory slots the player must have in each tab -- do not set this lower than 1.
        
    FreeInventory 2
    };

    // INTERNAL VARS
    var status = -1;
    var 
    rewardItems = Array();
    var 
    rewardWeights = Array();
    var 
    rewardQuantity = Array();
    var 
    totalWeights = Array();
    var 
    rng = new Random();

    function 
    start(){
        if(
    enabled || cm.getPlayer().isGM()){
            
    //Split the reward items
            
    for(var 0rewards.lengthi++){
                if(
    == 0){
                    
    rewardItems.push(rewards[i]);
                } else if (
    == 1) {
                    
    rewardQuantity.push(rewards[i]);
                } else {
                    
    rewardWeights.push(rewards[i]);
                    
    //For each weight, generate the sum of all previous weights
                    
    var total 0;
                    for(var 
    0rewardWeights.lengthk++){
                        
    total += rewardWeights[k];
                    }
                    
    totalWeights.push(total);
                }
            }
            
    action(1,0,0);
        } else {
            
    cm.sendOk("Something clicks inside the Gachapon, then it stops altogether.  It doesn't respond.\r\n#r(The Gachapon is currently disabled.)#k");
            
    cm.dispose();
            return;
        }
    }

    function 
    action(modetypeselection){
        if(
    mode == && selection != 99){
            
    status++;
        } else {
            
    cm.dispose();
            return;
        }
        
        if(
    status == 0){
            
    cm.sendSimple(getMainMenu());
        } else {
            if(
    selection == 2){ //show rewards
                
    if(!showRewards && !cm.getPlayer().isGM()){
                    
    cm.sendOk("#rReward showing has been disabled.#k\r\n#b#L99#Okay.#l#k");
                    
    cm.dispose();
                } else {
                    
    cm.sendOk("List of rewards for this gachapon: \r\n" getRewardsDisplay() + "\r\n#b#L99#Okay.#l#k");
                    
    cm.dispose();
                }
            } else { 
    //use ticket
                
    if(checkInventorySpace()){
                    if(
    cm.haveItem(Constants.Ticket1)){
                        
    cm.gainItemSilent(Constants.Ticket, -1);
                        var 
    reward getRewardIndex();
                        
    cm.gainItem(rewardItems[reward], rewardQuantity[reward]);
                        
    cm.sendSimple(getRewardMessage(reward));
                    } else {
                        
    cm.sendOk("You do not have a #d#v" Constants.Ticket "##z" Constants.Ticket "##k.\r\n#b#L99#Okay.#l#k");
                        
    cm.dispose();
                    }
                } else {
                    
    cm.sendOk("The Gachapon beeps once, then stops.  It doesn't respond.  #r(You must have " Constants.FreeInventory " free inventory slots in each tab.)#k\r\n#b#L99#Okay.#l#k");
                    
    cm.dispose();
                    return;
                }
            }
        }
    }

    function 
    getMainMenu(){
        var 
    retText "The Gachapon emits a muffled (clunk) noise.\r\n#b";
        
    retText += "#L1#Use a #k#d#v" Constants.Ticket "##z" Constants.Ticket "##k#b#l\r\n";
        if(
    showRewards || cm.getPlayer().isGM()){
            
    retText += "#L2#Display the list of rewards.#l\r\n";
        }
        
    retText += "#L99#(Never mind...)#l\r\n";
        
    retText += "#k";
        return 
    retText;
    }

    function 
    getRewardMessage(reward){
        var 
    retText "The Gachapon beeps.  A series of unidentifiable noises follows, then an item rolls out into the reward slot.  You pick it up.\r\n";
        
    retText += "#rYou have gained the following:#k\r\n#d";
        
    retText += rewardQuantity[reward] + "x #v" rewardItems[reward] + "##z" rewardItems[reward] + "##k\r\n";
        
    retText += "You currently have #r" getRemainingTickets() + "#k #z" Constants.Ticket "# remaining.\r\n";
        
    retText += "#b#L1#Use another ticket.#l\r\n";
        
    retText += "#L99#Stop using the Gachapon.#l#k\r\n";
        return 
    retText;
    }

    function 
    getRewardIndex(){
        
    //random # between 1 and the sum of all weights
        
    var weight rng.nextInt(totalWeights[totalWeights.length 1] + 1);
        var 
    retIndex 0;
        while(
    retIndex totalWeights.length 1){
            if(
    weight totalWeights[retIndex 1] && weight >= totalWeights[retIndex]){
                break;
            }
            
    retIndex++;
        }
        return 
    retIndex;
    }

    //Check for slots in each tab
    function checkInventorySpace(){
        for(var 
    1<= 5i++){
            if(
    cm.getPlayer().getInventory(MapleInventoryType.getByType(i)).getNumFreeSlot() < Constants.FreeInventory){
                return 
    false;
            }
        }
        return 
    true;
    }

    function 
    getInventoryType(itemID){
        return 
    Math.floor(itemID 1000000);
    }

    function 
    getRemainingTickets(){
        return 
    cm.getPlayer().getInventory(MapleInventoryType.getByType(getInventoryType(Constants.Ticket))).countById(Constants.Ticket);
    }

    function 
    getRewardsDisplay(){
        var 
    ret "#r";
        for(var 
    0rewardItems.lengthi++){
            if(
    rewardQuantity[i] > 1){ //don't show the quantity if there's only one
                
    ret += rewardQuantity[i] + "x ";
            }
            
    ret += "#v" rewardItems[i] + "##z" rewardItems[i] + "# ";
            if(
    showRewardChances){
                
    ret += "#k#b(" + (rewardWeights[i] / totalWeights[totalWeights.length 1] * 100).toFixed(3) + "%)#k#r";
            }
            
    ret += "\r\n";
        }
        
    ret += "#k";
        return 
    ret;



  2. #2
    Apprentice hackerx3 is offline
    MemberRank
    Aug 2009 Join Date
    14Posts

    Re: Generic Gachapon NPC

    Merry Chirstmas :)

  3. #3
    Account Upgraded | Title Enabled! oxysoft is offline
    MemberRank
    Nov 2008 Join Date
    Canada, QCLocation
    1,400Posts

    Re: Generic Gachapon NPC

    this is a nice script

  4. #4
    C# developer xStr0nGx is offline
    MemberRank
    Dec 2013 Join Date
    UnknownLocation
    659Posts

    Re: Generic Gachapon NPC

    This is a clean and nice script, Good job!

  5. #5
    Moderator Eric is offline
    ModeratorRank
    Jan 2010 Join Date
    DEV CityLocation
    3,188Posts

    Re: Generic Gachapon NPC

    now THAT's an npc script. I love the percentage idea! I never knew you could do that thing with the constants either. Nice work ;p

  6. #6
    jRvdJxwvjhs Linkerzz is offline
    MemberRank
    Nov 2008 Join Date
    NorwayLocation
    345Posts

    config Re: Generic Gachapon NPC

    How to get "Generic Gachapon" to work with older versions (v82) of MS:
    First off we need to change the reward item id's so it doesn't disconnect us.

    Replace with: (As example)
    Code:
    //Rewards, listed as (ItemID, Quantity, Weight).  Weights are relative, and do not have to add up to 100. 
    var rewards = Array( 
        4000003,1,20, 
        1112000,1,30, 
        4000006,2,1
        5072000,1,70 
    ); 
    
    Constants = { 
        //ItemID to use as the "ticket" (https://mapletip.com/etc-items/Tetris%20Piece/4030004)
        Ticket : 4030004, 
        //Number of free inventory slots the player must have in each tab -- do not set this lower than 1. 
        FreeInventory : 2 
    };

    Erase "Silent" under:
    Code:
    if(cm.haveItem(Constants.Ticket, 1)){
    cm.gainItemSilent(Constants.Ticket, -1);

    Thanks for the release AngelSpirit!

    EDIT: @Cygnus - Yeah this was just a quick spoonfeed for nubs. tl;dr disregard me I suck

    If you want to add in the gainItemSilent(); for this one npc,
    I can't assume it would be too hard to just paste it in from a higher version.

    Look for "gainItem(" in AbstractPlayerInteraction.java and hold down CTRL while hovering your mouse over the name to navigate to the method. (check differences between the new/old functions).
    quote me if i've got that wrong
    Last edited by Linkerzz; 21-06-15 at 10:38 PM. Reason: Updated

  7. #7
    Enthusiast Rizener is offline
    MemberRank
    Aug 2014 Join Date
    26Posts

    Re: Generic Gachapon NPC

    Doesn't Work on v62?

  8. #8
    :l Cygnus is offline
    MemberRank
    Mar 2015 Join Date
    f425Location
    237Posts

    Re: Generic Gachapon NPC

    Quote Originally Posted by Rizener View Post
    Doesn't Work on v62?
    First off; Hate to break it to you, copy-pasting higher versions scripts doesn't always work.
    Second, if you tried reading
    Quote Originally Posted by Linkerzz View Post
    To get it to work with even earlier versions, such as v62, we need to:
    Third, imo you're better of re-writing the script utilizing it's weight/reward system if you're going to use it for v62

  9. #9
    jRvdJxwvjhs Linkerzz is offline
    MemberRank
    Nov 2008 Join Date
    NorwayLocation
    345Posts

    Re: Generic Gachapon NPC

    Quote Originally Posted by Rizener View Post
    Doesn't Work on v62?
    I got it to work fine in LeaderMS source. What's the error say when you click the NPC?

  10. #10
    Account Upgraded | Title Enabled! Syre is offline
    MemberRank
    Jan 2013 Join Date
    700Posts

    Re: Generic Gachapon NPC

    Very well done, I must say. Nice!



Advertisement