Jump to content

meko

Core Developers
  • Content Count

    363
  • Joined

  • Days Won

    46

Posts posted by meko


  1. not sure clone() is a good idea, because it requires the cloned player to be online, but if that's intended then try this:

    .@mobGID = clone("prontera", 157, 167, "HALL::OnMobDead", 150005, 0, 0x0); // make the clone
    setunitdata(.@mobGID, UDT_MODE, getunitdata(.@mobGID, UDT_MODE) &~ (1 | 128)); // prevent from attacking & moving 

    this makes it unable to move or attack, but doesn't (and can't) prevent the player from attacking it

     

    An alternative could be to use a NPC instead and change its appearance by manipulating UDT_SEX, UDT_HAIRSTYLE, UDT_HAIRCOLOR, UDT_HEADBOTTOM, UDT_HEADMIDDLE, UDT_HEADTOP, UDT_CLOTHCOLOR, UDT_SHIELD, and UDT_WEAPON, but I don't know if the Gravity client supports dynamic NPCs


  2. Actually it's pretty useful, it allows to pass custom variables instead of having the functions register hardcoded variables, and it avoids having to use getd. So if your function needs to return more than one value it can just ask for a variable as an argument, and fill it with the return data. The alternative would be to implode() the values, return, and then explode() after the function call, which is much dirtier.


  3. if all you want to do is drop an item, this can be done directly in the mob db

     

    about rand() you cannot use a custom seed; Hercules generates its own

     

    With killedrid you could get the mob id with getunitdats(UDT_CLASS, killedrid) and then you can get further information with getmonsterinfo()


  4. setarray() does not create the structure of the array; it sets multiple elements of the array at the same time.

    this means every time setarray() is called it will overwrite the values.

    arrays do not need to be declared. every variable is always implicitly an array

     

    Also, there's another problem: variable$[2] = 1;

    You are setting an integer as value of a string variable

    If what you need is an array of integers then remove the "$" in the variable name


  5. I do see your problem though:

    if (.@mapa$ != "pvp_n_1-5,guild_vs2,pvp_n_1-3")
    

    Here you are checking for a map called "pvp_n_1-5,guild_vs2,pvp_n_1-3", not for 3 different maps.

     

    Try replacing by:

    if (.@mapa$ != "pvp_n_1-5" && .@mapa$ != "guild_vs2" && .@mapa$ != "pvp_n_1-3")
    

  6. first, remove the existing drop:

    delmonsterdrop(<mob id or name>, <item id>)
    

     

    then add it back, with a different drop rate:

    addmonsterdrop(<mob id or name>, <item id>, <rate>)
    

     

    This will only change one monster at a time, so you must hard-code all the mob ids in your script.

     

    An alternative could be to iterate over ALL monsters in a loop starting from id 1001 and checking with getmonsterinfo() if the race is RC_Fish, but the loop would be insanely long and block the thread (so requires freeloop), which would make the server completely unresponsive while processing the loop. If you only plan to do it in OnInit or when a custom atcommand is called it would probably be fine though.


  7. When a function is invoked, the arguments are pushed to the stack, but if an argument is a scope variable its reference is also pushed. This means you can access variables of the parent scope from within a function.

     

    function do_something {
        setarray(getarg(0), 69, 42, 1337);
        return;
    }
    
    debugmes(.@var[0]); // <= 0
    debugmes(.@var[1]); // <= 0
    debugmes(.@var[2]); // <= 0
    
    do_something(.@var[0]);
    
    debugmes(.@var[0]); // <= 69
    debugmes(.@var[1]); // <= 42
    debugmes(.@var[2]); // <= 1337
    

     

     


  8. You spawn your monster like this:

    .@mobGID = monster("prontera", 150, 150, "Poring", PORING, 1);
    

     

    And you manipulate like this:

    // to prevent from moving:
    setunitdata(.@mobGID, UDT_MODE, getunitdata(.@mobGID, UDT_MODE) &~ 1);
    
    // to prevent from attacking:
    setunitdata(.@mobGID, UDT_MODE, getunitdata(.@mobGID, UDT_MODE) &~ 128);
    
    // to change stats:
    setunitdata(.@mobGID, UDT_STR, 11); // <= change those numbers
    setunitdata(.@mobGID, UDT_AGI, 95);
    setunitdata(.@mobGID, UDT_VIT, 2);
    setunitdata(.@mobGID, UDT_INT, 55);
    setunitdata(.@mobGID, UDT_DEX, 10);
    setunitdata(.@mobGID, UDT_LUK, 40);
    

  9. the x1,y1,x2,y2 is the square area composed of the coordinates of the top-left tile and the bottom-right tile

     

    Let's imagine a grid of x,y coordinates:

     

    0,0   0,1   0,2   0,3   0,4

     

    1,0   1,1   1,2   1,3   1,4

     

    2,0   2,1   2,2   2,3   2,4

     

    3,0   3,1   3,2   3,3   3,4

     

    4,0   4,1   4,2   4,3   4,4

     

     

    Let's say you want the coordinates in red to be basilica;

    The top-left red tile is 1,1 in this case. This would be your x1,y1.

    The bottom-right tile is 3,3. This would be your x2,y2

     

    so you'd write setcell("map",   1,1,    3,3,      cell_basilica, true)

     

     

    If you do not know the coordinates you can simply walk to it with your character and use the @where command


  10. here's a rough draft (not tested)

     

    -	script	PvP Ranking	FAKE_NPC,{
    
    OnPCKillEvent:
        pvp_rank[.this_week] += 3; // raise our own pvp rank
        dispbottom("You gain 3 points on PvP Rank");
        attachrid(killedrid);
        pvp_rank[.this_week] = max(0, pvp_rank[.this_week] - 3); // decrease their pvp rank
        dispbottom("You received -3 points penalty on PvP Rank");
        end;
    
    OnPCLoginEvent:
    OnClaimReward:
        .@char = getcharid(CHAR_ID_CHAR);
        if ($pending_badges[.@char] < 1) {
            end;
        }
    
        pvp_rank[$last_week] = 0;
        dispbottom(sprintf("PvP Rank: you obtained %i points this week, putting you at rank %i.",
            $pending_points[.@char], $pending_rank[.@char] + 1));
        dispbottom(sprintf("Reward: %i badges.", $pending_badges[.@char]));
        getitem(Rok_Star_Badge, $pending_badges[.@char]);
    
        $pending_badges[.@char] = 0;
        $pending_points[.@char] = 0;
        $pending_rank[.@char] = 0;
        end;
    
    OnInit:
        .top_len = 10; // we want a top 10
    
        // fallthrough
    
    OnSun0001:
        // every Sunday at 00:01 AM
        $last_week = .this_week;
        .this_week = atoi(gettimestr("%y%W", 4)); // YYWW
    
        if ($last_week < 1) {
            end; // this is our first week running this script
        }
    
        .@count = query_sql(sprintf("SELECT c.char_id, c.name, r.value"
                      "FROM `char_reg_num_db` r "
                      "JOIN `char` c ON r.char_id = c.char_id "
                      "WHERE `key`='pvp_rank' AND `index`='%i' "
                      "ORDER BY `value` DESC "
                      "LIMIT " + .top_len + ";", $last_week),
                      .top_char[0], .top_char$[0], .top_points[0]); // store that info so it can be reused throughout the week
    
        query_sql(sprintf("DELETE FROM `char_reg_num_db` WHERE `key`='pvp_rank' AND `index` <= %i", $last_week)); // janitor task
    
        for (.@i = 0; .@i < .@count; .@i++) {
            .@badges = (10 * .top_len) - (10 * .@i); // the badges this player won
            .@char = .top_char[.@i];
            .@acc = charid2rid(.@char);
    
            $pending_badges[.@char] += .@badges;
            $pending_points[.@char] = .top_points[.@i];
            $pending_rank[.@char] = (.@i + 1);
    
            if (.@acc > 0) {
                addtimer(rand(5000), "PvP Ranking::OnClaimReward", .@acc);
            }
        }
        end;
    }
    

    You'll notice I did +3 and -3 for both killing and being killed; This is on purpose, else someone could just make 2 characters and kill each other to keep getting +1 every time (+3, -2)

     

     

    To display the top 10 from last week in a npc you'd do something like:

    mes("Here's the ranking for last week:");
    next();
    
    if (getvariableofnpc(.top_char[0], "PvP Ranking") < 1) {
        mes("(no ranking available for that week)");
        next();
    }
    
    .@max = getvariableofnpc(.top_len, "PvP Ranking");
    for (.@i = 0; .@i < .@max; .@i++) {
        .@points = getvariableofnpc(.top_points[.@i], "PvP Ranking");
        if (.@points < 1) {
            break;
        }
        mes(sprintf("%i. %s — %i points.", .@i + 1,
            getvariableofnpc(.top_char$[.@i], "PvP Ranking"), .@points));
        next();
    }
    

  11. 
    

    .@count = query_sql("SELECT c.name, r.value AS points "

    "FROM `char_reg_num_db` r "

    "JOIN `char` c ON r.char_id = c.char_id "

    "WHERE `key`='brokeemp' AND `index`='0' "

    "ORDER BY `value` DESC "

    "LIMIT 10;",

    .@char$[0], .@points[0]);

     

    for (.@i = 0; .@i < .@count; .@i++) {

    mes(sprintf("%d. %s — %d points.", .@i + 1, .@char$[.@i], .@points[.@i]));

    }

     


  12. maybe something like this:

    map,x,y,dir	script	npc name	sprite,{
    
        if (gettime(GETTIME_HOUR) == 15 || gettime(GETTIME_HOUR) == 19) {
            mes("I will now teleport you to the map.");
            close2();
    
            // check the hour again, because the player can wait before closing
            if (gettime(GETTIME_HOUR) == 15 || gettime(GETTIME_HOUR) == 19) {
                warp(.dest_map$, .dest_x, .dest_y);
                addtimer(600000, strnpcinfo(NPC_NAME) + "::OnComeBack"); // 10 minutes
                end;
            }
        }
    
        mes("Sorry, I cannot teleport you right now.");
        next();
        mes("Come back at 15H or 19H.");
        close;
    
    OnComeBack:
        warp("SavePoint", 0, 0);
        end;
    
    OnInit:
        .dest_map$ = "destination map";
        .dest_x = 0;
        .dest_y = 0;
    
        // fallthrough
    
    OnHour16:
    OnHour20:
        // force any remaining player to come back if for whatever reason they are still there
        .@count = getunits(BL_PC, .@players, false, .dest_map$);
        for (.@i = 0; .@i < .@count; .@i++) {
            deltimer(strnpcinfo(NPC_NAME) + "::OnComeBack", .@players[.@i]);
            addtimer(0, strnpcinfo(NPC_NAME) + "::OnComeBack", .@players[.@i]);
        }
        end;
    }
    

  13. maybe something like this:

    OnPCKillEvent:
        if (rand(10) != 1) end; // artificial drop rate (1 in X chances to drop)
        delitem(Baphomet_Card, 1, killedrid); // force "drop"
        getitem(Baphomet_Card, 1); // force "pick-up"
        announce(sprintf("%s killed %s and obtained their Baphomet Card.",
            strcharinfo(PC_NAME), strcharinfo(PC_NAME, "unknown", killedrid)), bc_all);
        end;
    
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.