Jump to content

Winterfox

Members
  • Posts

    248
  • Joined

  • Last visited

  • Days Won

    19

Everything posted by Winterfox

  1. Stimmt, das hatte ich ja auch angesprochen. Es ist einfach dann sehr viel Inhalt und auch relativ komplex. Dessen sollte man sich aber finde ich bewusst sein, wenn man Pre-Renewal benutzen möchte. Ich finde solche Sachen werden oft übersehen oder unterschätzt. Deswegen sind viele Server sehr ähnlich oder setzen diese Dinge nicht vernünftig um.
  2. Hallo, ich befürchte du wirst nicht mehr viele Deutsche in dieser Community antreffen. Ragnarok hat einen ziemlichen Abwärtstrend außerhalb der asiatischen Länder scheint es und man trifft generell nicht mehr so viele Leute hier an. Ich weiß nicht ob es Server gibt, die genau so sind wie du das hier beschreibst, aber auf den ersten Blick erscheint mir dein Setup nicht so ungewöhnlich. Grundsätzlich denke ich aber, dass das Konzept durchaus funktionieren kann, sofern man sich Gedanken darüber macht, wie man einzigartige Inhalte und Events einbaut. Reine Random Optionen auf Items und Lootboxen werden dafür denke ich nicht ausreichen. Weshalb eigentlich Pre-Renewal und das Klassenlimit? Das ist etwas das ich häufig sehe, aber noch nie verstanden habe. Am Ende des Tages nimmt einem das doch viel Spielinhalt (Maps und Mobs die auf Renewal und neue Klassen optimiert sind), weil man sie entweder aufwändig anpassen oder unzugänglich lassen muss. Dabei ist der alte Ragnarok Inhalt schon ziemlich ausgelutscht. Die andere Sache ist natürlich, was bedeutet für dich Pay to Win? Reden wir hier von starken Items oder schon von EXP-Boosts, die dir eigentlich nur Zeit sparen? Denn wenn du da sehr strikt bist und so etwas wie den Coinshop hast, wirst du Probleme haben, den Server zu finanzieren. Gepard Shield ist zum Beispiel sehr gut, meines Wissens nach aber auch kostspielig. Außer du sagst dir ist es das Wert alles aus deiner Tasche zu bezahlen. Warum multiclienting? Wenn dein Fokus auf Fairness ist, was ich aufgrund von kein Pay to Win annehme, widerspricht sich das mit multiclienting für mich. Bei Features und Commands solltest du bedenken, dass es wichtig ist, Quellen zu haben, die Geld aus der Ökonomie wieder entfernen, sonst steigt die Inflation schnell an. Durch den @storage commands umgehst du zum Beispiel die Storagegebühr. Übrigens wenn es dir darum geht, dass Gameplay zu strecken, kannst du auch einfach statt alle Drops zu erhöhen, die Drops für Cards usw. auf deren Standardwerten lassen. Dadurch und durch die langsame Respawnzeit, die MVPs haben, dauert es sowieso relativ lange, bis jemand da eine bestimmte Ausstattung hat. Denn Random Optionen führen ja im Endeffekt nur zu einem Metashift, dass jeder letztendlich die richtigen Items und Karten hat und dann auf Random Optionen optimiert. Es ist letztendlich nur eine weiteres Ebene auf den bereits bestehenden Ebene der Gegenstandsaufwertungen. Das ist denke ich auch nicht, was die meisten Leute halten wird, denn diese Systeme werden von Ragnarok ja selbst konstant hinzugefügt, wie Shadowgear usw. und das führt nicht dazu, dass die Spieler genau deswegen dabei bleiben. Letzendlich denke ich, ist das Problem immer fehlender neuer Inhalt, den man entweder selbst portieren muss, weil rAthena nicht hinterher kommt oder Quellen fehlen oder man muss etwas eigenes schaffen. Aber es ist schön zu sehen, dass es doch noch einzelne Leute gibt, die sich für Ragnarok interessieren und sich Gedanken machen. Ich bin gespannt auf deine Gedanken dazu. Du kannst mich auch gern im Discord adden oder Fragen stellen zum Thema Ragnarok Server.
  3. Why do you let the script fall trough to the label? If you want to continue the script after the destination is reached, you can simply let the script end after unitwalk and it will automatically pick up at the label after it reached the finale destination.
  4. - script hourly_point_main -1,{ OnInit: .npc_name$ = strnpcinfo(3); .reward_minutes = 1; bindatcmd("check", .npc_name$ + "::OnAtcommand"); end; OnAtcommand: dispbottom("Accumulated " + #daily_minute_count); end; OnPCLoginEvent: addtimer(.reward_minutes * 10000, .npc_name$ + "::OnUpdate"); end; OnUpdate: deltimer(.npc_name$ + "::OnUpdate"); addtimer(.reward_minutes * 10000, .npc_name$ + "::OnUpdate"); if (checkvending() & 2) { end; } #daily_minute_count += .reward_minutes; switch(#daily_minute_count) { case 60: // 60 minutes #CASHPOINT += 1; getitem 677,1; break; case 120: // 120 minutes #CASHPOINT += 1; getitem 677,1; break; case 180: // 180 minutes #CASHPOINT += 1; getitem 677,1; break; case 240: // 240 minutes #CASHPOINT += 1; getitem 677,1; break; case 300: // 300 minutes #CASHPOINT += 1; getitem 677,1; break; case 360: // 360 minutes #CASHPOINT += 1; getitem 677,1; break; case 420: // 420 minutes #CASHPOINT += 1; getitem 677,1; break; case 480: // 480 minutes #CASHPOINT += 1; getitem 677,1; #daily_minute_count = 0; // reset. break; default: break; } }
  5. *unitwalk <GID>,<x>,<y>{,"<event label>"}; Use the event label to issue the next unitwalk after the last has finished. OnDestinationReached: if(!unitexists(.gid)) end; if(.move_count == .curr_pointer) .curr_pointer = 0; else .curr_pointer += 2; unitwalk(.gid, .path[.curr_pointer], .path[.curr_pointer + 1], "MVP_EVENT::OnDestinationReached"); end;
  6. Hallo, ich bin auch ab und zu noch da. Hauptsächlich um zu sehen, ob es interessante Script-Anfragen oder Fragen nach Hilfe mit Scripting gibt.
  7. - script GLOBAL -1,{ OnWhisperglobal: if(getgroupid() < 5 || MESSAGE_COOLDOWN > gettimetick(2)) end; announce(strcharinfo(0) + ": " + @whispervar0$, bc_all); MESSAGE_COOLDOWN = gettimetick(2) + 20; }
  8. You missed the part with the pausing of the reminder. - script VIP_REMINDER -1,{ OnInit: .pause_days = 7; end; OnPCLoginEvent: if(vip_status(VIP_STATUS_ACTIVE) || #REMINDER_COOLDOWN > gettimetick(2)) end; mes "[Premium Reminder Service]"; mes "Your Premium Status is NOT ACTIVE"; mes "Please consider using our premium service to get more benefits."; mes "Do you want to pause this reminder for 7 days?"; next; if(select("Yes.:No." == 2) { mes "[Premium Reminder Service]"; mes "You will get a reminder on next login."; end; } #REMINDER_COOLDOWN = gettimetick(2) + 86400 * .pause_days; mes "[Premium Reminder Service]"; mes "The reminder has been paused until " + gettimestr("%Y-%m/%d %H:%M:%S", 21, #REMINDER_COOLDOWN); close; }
  9. /* setcell types */ export_constant(CELL_WALKABLE); export_constant(CELL_SHOOTABLE); export_constant(CELL_WATER); export_constant(CELL_NPC); export_constant(CELL_BASILICA); export_constant(CELL_LANDPROTECTOR); export_constant(CELL_NOVENDING); export_constant(CELL_NOCHAT); export_constant(CELL_MAELSTROM); export_constant(CELL_ICEWALL); export_constant(CELL_NOBUYINGSTORE);
  10. prontera,155,177,5 script Example 100,{ end; OnAgitStart: OnAgitStart2: OnAgitStart3: initnpctimer; end; OnAgitEnd: OnAgitEnd2: OnAgitEnd3: stopnpctimer; end; OnTimer1000: initnpctimer; OnInit: .@owning_guild_id = getcastledata("payg_cas04", CD_GUILD_ID); if(.@owning_guild_id == 0) { .@owner_name$ = "Unowned"; } else { .@owner_name$ = getguildname(.@owning_guild_id); } delwaitingroom(); waitingroom(.@owner_name$, 0); }
  11. You could simplify your script by creating a crafting subroutine that takes your crafting product and requirements instead of having the same logic repeated for every item. - script Work Table FAKE_NPC,{ // i leave out the most stuff of your npc for the clarity of this example. soundeffect "menu.wav",0; mes "=============================="; mes "^ff0000 Any item created unattended by using the Work Table can be stolen by other players !! "; mes "=============================="; mes "Private Work Table are shared with those who have acsess only !!^000000"; mes "=============================="; next; soundeffect "menu.wav",0; mes "Select"; switch(prompt("- Heat Resistant Barrel:- Whatever:- Cancel")) { case 1: // Product ID, Product Amount, Requirement ID, Requirement Type (Normal / Rental), Requirement Amount, ... callsub(S_Crafting_Init, 40189, 1, 40191, 0, 1, 40084, 0, 1, 40085, 0, 1); case 2: callsub(S_Crafting_Init, 40190, 1, 40192, 0, 1, 40085, 0, 1, 40086, 0, 1); case 255: goto OnCancel; } S_Crafting_Init: .@product_id = getarg(0); .@product_amount = getarg(1); for(.@i = 2; .@i < getargcount(); .@i += 3) { .@next_start_index = getarraysize(.@product_requirements); .@product_requirements[.@next_start_index] = getarg(.@i); // ID .@product_requirements[.@next_start_index + 1] = getarg(.@i + 1); // Type .@product_requirements[.@next_start_index + 2] = getarg(.@i + 2); // Amount } next; soundeffect "menu.wav",0; mes "^ff0000 Require"; for(.@i = 0; .@i < getarraysize(.@product_requirements); .@i += 3) { mes "- " + .@product_requirements[.@i + 2] + " " + getitemname(.@product_requirements[.@i]); if(.@product_requirements[.@i + 1] == 1) { .@item_amount = rentalcountitem(.@product_requirements[.@i]); } else { .@item_amount = countitem(.@product_requirements[.@i]); } if(.@item_amount < .@product_requirements[.@i + 2]) { .@not_enough_items = 1; } } if(.@not_enough_items == 1){ close; } soundeffect "menu.wav",0; if(select("- Start:- Cancel") == 2) { goto OnCancel; } if(countitem(40007) == 1){ process_points += 1; dispbottom("Gained +1 Processing Points"); } for(.@i = 0; .@i < getarraysize(.@product_requirements); .@i += 3) { if(.@product_requirements[.@i + 1] == 0) { delitem(.@product_requirements[.@i], .@product_requirements[.@i + 2]); } } setarray(getd("$wrkb_" + .@wrkb_id + "_products"), .@product_id, .@product_amount); goto OnCraftingStart; OnCancel: next; soundeffect "menu.wav",0; mes "Process Cancel"; close; }
  12. You forgot the brackets of the GetArraySize call on line 16. for(set @i,0; @i<=GetArraySize($DropsSorte)-1; set @i,@i+2) mes @i/2+": "+$DropsSorte[@i+1]+" "+GetItemName($DropsSorte[@i]);
  13. You can use getinventorylist and filter all items that aren't equipment or currently equipped equipment. prontera,150,150,6 script Demo 85,{ disable_items; getinventorylist; for(.@i = 0; .@i < @inventorylist_count; .@i++) { .@item_type = getiteminfo(@inventorylist_id[.@i], ITEMINFO_TYPE); if ((.@item_type == IT_ARMOR || .@item_type == IT_WEAPON || .@item_type == IT_SHADOWGEAR) && !@inventorylist_equip[.@i]) { .@item_ref = getarraysize(.@equipment_id_list); .@equipment_id_list[.@item_ref] = @inventorylist_id[.@i]; .@menu_labels$[.@item_ref] = getitemname(@inventorylist_id[.@i]); } } .@selected_item_ref = select(implode(.@menu_labels$, ":") - 1; next; mes "You selected: " + getitemname(.@equipment_id_list[.@selected_item_ref]) + "."; close; }
  14. It is possible, but you have to write the respawn logic yourself. Here is an untested example: - script DYNAMIC_MOB_SPAWN -1,{ OnInit: .mob_id = 1002; .mob_amount = 10; .mob_map$ = "prontera"; .mob_start_coords_x = 150; .mob_start_coords_y = 150; .mob_end_coords_x = 160; .mob_end_coords_y = 160; .no_spawn_start_hour = 16; .no_spawn_end_hour = 18; if(callsub("S_No_Respawn_Hour")) { .@curr_mob_amount = .mob_amount - $dead_mobs_amount; if(.@curr_mob_amount) { callsub("S_Spawn_Mobs", .@curr_mob_amount); } .no_respawn = 1; end; } $dead_mobs_amount = 0; callsub("S_Spawn_Mobs", .mob_amount); end; OnMobDead: if(.no_respawn) { $dead_mobs_amount++; end; } callsub("S_Spawn_Mobs", 1); end; OnHour00: OnHour01: OnHour02: OnHour03: OnHour04: OnHour05: OnHour06: OnHour07: OnHour08: OnHour09: OnHour10: OnHour11: OnHour12: OnHour13: OnHour14: OnHour15: OnHour16: OnHour17: OnHour18: OnHour19: OnHour20: OnHour21: OnHour22: OnHour23: if(callsub("S_No_Respawn_Hour")) { .no_respawn = 1; end; } .no_respawn = 0; if(!$dead_mobs_amount) end; callsub("S_Spawn_Mobs", $dead_mobs_amount); $dead_mobs_amount = 0; end; S_Spawn_Mobs: areamonster(.mob_map$, .mob_start_coords_x, .mob_start_coords_y, , .mob_end_coords_x, .mob_end_coords_y, "--ja--", .mob_id, getarg(0), "DYNAMIC_MOB_SPAWN::OnMobDead"); return; S_No_Respawn_Hour: .@curr_hour = gettime(DT_HOUR); if(.@curr_hour >= .no_spawn_start_hour && .@curr_hour < .no_spawn_end_hour) { return 1; } return 0; }
  15. I didn't test it, but this should give you an idea how to achieve what you want: askald,104,205,5 script PvP Gold Room 4_F_KAFRA1,{ doevent "gold_room_main::OnTalk"; } // warp portal back prontera ordeal_3-2,123,123,0 warp gold_room_back_prt 1,1,prontera,155,181 // peco peco summon ordeal_3-2,0,0,0,0 monster Gold 1954,100,60000,0,"gold_room_main::OnKill" - script gold_room_main -1,{ OnInit: // gold room map .map$ = "ordeal_3-2"; // entrance fee .zeny_cost = 500000; // rate to get gold .rate = 100; // points per kill .points_per_kill = 2; // gold random amount setarray(.gold_amount, 1, 5); setmapflag .map$,mf_noteleport; setmapflag .map$,mf_nobranch; setmapflag .map$,mf_nosave; setmapflag .map$,mf_nomemo; setmapflag .map$,mf_noreturn; setmapflag .map$,mf_nowarp; setmapflag .map$,mf_nowarpto; setmapflag .map$,mf_pvp; end; OnTalk: mes "Enter Gold Room?"; next; if(.zeny_cost) { mes F_InsertComma(.zeny_cost) + " Zeny"; close; } switch(select("Enter Gold Room","Exchange Gold Point","Information")) { case 1: if (Zeny < .zeny_cost) { mes "Not enough Zeny."; break; } Zeny -= .zeny_cost; warp .map$,0,0; end; case 2: mes "You got " + F_InsertComma(#GOLDPOINTS) + " Points"; input .@value,0,#GOLDPOINTS; if (.@value == 0) { mes "Exchange canceled."; break; } if(checkweight(969, .@value)) { #GOLDPOINTS -= .@value; getitem(969, .@value); mes "Gained " + .@value + " Gold."; break; } break; case 3: mes "In this room you will have the chance to get " + .points_per_kill + " points for each monster killed, but if another player kills you you lose all your points! 1 point gets you 1 gold"; break; } close; OnKill: if(rand(100) < .rand) { #GOLDPOINTS += .points_per_kill; dispbottom "You gained " + .points_per_kill + " Points. You do have " + F_InsertComma(#GOLDPOINTS) + " Points now."; } end; OnPCKillEvent: if (strcharinfo(3) != .map$) end; .@killer_name$ = strcharinfo(0); .@killed_name$ = rid2name(killedrid); .@killed_char_id = getcharid(0, .@killed_name$); .@killed_gold_points = getvar("#GOLDPOINTS", .@killed_char_id); #GOLDPOINTS += .@killed_gold_points; dispbottom("You killed " + .@killed_name$ + " and got all his points. You do have " + F_InsertComma(#GOLDPOINTS) + " Points now."; attachrid(killedrid); #GOLDPOINTS = 0; dispbottom("You died and lost all your points to " + .@killer_name$ + "."); }
  16. Well, what I posted was an example for you to modify yourself to fit your needs. If you want to be able to only mark one specific mob on a map by mob id you can do it like this: - script MOB_MARKER -1,{ OnInit: bindatcmd("markmobs", strnpcinfo(3) + "::OnMarkMobs"); bindatcmd("unmarkmobs", strnpcinfo(3) + "::OnUnmarkMobs"); end; function delete_viewpoints { freeloop(1); for(.@i = 0; .@i < getarraysize(@viewpoints_x); .@i++) { viewpoint(2, @viewpoints_x[.@i], @viewpoints_y[.@i], (.@i + 1), 0xFF0000); } freeloop(0); deletearray(@viewpoints_x, getarraysize(@viewpoints_x)); deletearray(@viewpoints_y, getarraysize(@viewpoints_y)); } OnMarkMobs: if(.@atcmd_numparameters != 1) { dispbottom("Usage: @markmobs MobID"); end; } .@mob_id = atoi(.@atcmd_parameters$[0]); if((.@mob_name$ = strmobinfo(1, .@mob_id)) == "") { dispbottom("A mob with the Mob ID " + .@mob_id + " does not exist."); end; } getmapxy(.@map$, .@x, .@y); getmapunits(BL_MOB, .@map$, .@mobs); if(getarraysize(.@mobs) == 0) { dispbottom("There are no mobs on this map."); end; } if(getarraysize(@viewpoints_x) > 0) { delete_viewpoints(); } freeloop(1); for(.@i = 0; .@i < getarraysize(.@mobs); .@i++) { if(getunitname(.@mobs[.@i]) != .@mob_name$) { continue; } getunitdata(.@mobs[.@i], .@unit_data); .@viewpoint_index = getarraysize(@viewpoints_x); viewpoint(1, .@unit_data[UMOB_X], .@unit_data[UMOB_Y], (.@viewpoint_index + 1), 0xFF0000); @viewpoints_x[.@viewpoint_index] = .@unit_data[UMOB_X]; @viewpoints_y[.@viewpoint_index] = .@unit_data[UMOB_Y]; } freeloop(0); if(getarraysize(@viewpoints_x) == 0) { dispbottom("Mob ID " + .@mob_id + " was not found on the map."); end; } end; OnUnmarkMobs: if(getarraysize(@viewpoints_x) == 0) end; delete_viewpoints(); }
  17. I didn't test it so there might be slight typos or small bugs, but basically you can do it like this: - script MOB_MARKER -1,{ OnInit: .map$ = "yourmap"; bindatcmd("markmobs", strnpcinfo(3) + "::OnMarkMobs"); bindatcmd("unmarkmobs", strnpcinfo(3) + "::OnUnmarkMobs"); end; function unmark_mobs { freeloop(1); for(.@i = 0; .@i < getarraysize(.@viewpoints_x); .@i++) { viewpoint(2, @viewpoints_x[.@i], @viewpoints_y[.@i], (.@i + 1), 0xFF0000); } freeloop(0); deletearray(@viewpoints_x, getarraysize(@viewpoints_x)); deletearray(@viewpoints_y, getarraysize(@viewpoints_y)); return; } OnMarkMobs: if(getarraysize(@viewpoints_x) > 0) { unmark_mobs(); } getmapunits(BL_MOB, .map$, .@mobs); freeloop(1); for(.@i=0; .@i < getarraysize(.@mobs); .@i++) { getunitdata(.@mobs[.@i], .@unit_data); viewpoint(1, .@unit_data[UMOB_X], .@unit_data[UMOB_Y], (.@i + 1), 0xFF0000); @viewpoints_x[.@i] = .@unit_data[UMOB_X]; @viewpoints_y[.@i] = .@unit_data[UMOB_Y]; } freeloop(0); end; OnUnmarkMobs: if(getarraysize(@viewpoints_x) > 0) { unmark_mobs(); } }
  18. I see. I went with the first solution I came up with from the top of my head. But it isn't that hard to do it the way you are showing either. You simply can use an invisible npc with an OnTouchNPC label that teleports the mob back into the desired area. - script EXAMPLE_SPAWN -1,{ OnInit: areamonster("prontera", 151, 149, 155, 143, "", "poring", 2); } - script MOB_BOUNDARY_CELL -1,{ OnTouchNPC: unitwarp(getattachedrid(), "this", 153, 147); } prontera,150,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#01 -1,0,0 prontera,151,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#02 -1,0,0 prontera,152,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#03 -1,0,0 prontera,153,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#04 -1,0,0 prontera,154,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#05 -1,0,0 prontera,155,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#06 -1,0,0 prontera,156,150,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#07 -1,0,0 prontera,150,149,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#08 -1,0,0 prontera,150,148,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#09 -1,0,0 prontera,150,147,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#10 -1,0,0 prontera,150,146,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#11 -1,0,0 prontera,150,145,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#12 -1,0,0 prontera,150,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#13 -1,0,0 prontera,150,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#14 -1,0,0 prontera,151,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#15 -1,0,0 prontera,152,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#16 -1,0,0 prontera,153,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#17 -1,0,0 prontera,154,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#18 -1,0,0 prontera,155,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#19 -1,0,0 prontera,156,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#20 -1,0,0 prontera,156,149,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#21 -1,0,0 prontera,156,148,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#22 -1,0,0 prontera,156,147,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#23 -1,0,0 prontera,156,146,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#24 -1,0,0 prontera,156,145,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#25 -1,0,0 prontera,156,144,0 duplicate(MOB_BOUNDARY_CELL) MOB_BOUNDARY_CELL#26 -1,0,0
  19. This is not a topic for the scripting section.
  20. Try this: - script MOB_BOUNDARY -1,{ OnInit: // CONFIG .map$ = "prontera"; .check_interval = 1000; .center_x = 150; .center_y = 150; .range_x = 5; .range_y = 5; // CONFIG END .start_x = .center_x - .range_x; .start_y = .center_y - .range_y; .end_x = .center_x + .range_x; .end_y = .center_y + .range_y; areamonster(.map$, .start_x, .start_y, .end_x, .end_y, "", "poring", 1); freeloop(1); while(true) { deletearray(.@mobs, getarraysize(.@mobs)); getmapunits(BL_MOB, .map$, .@mobs); for(.@i = 0; .@i < getarraysize(.@mobs); .@i++) { getunitdata(.@mobs[.@i], .@mob_data); if( (.@mob_data[UMOB_X] < .start_x || .@mob_data[UMOB_X] > .end_x) || (.@mob_data[UMOB_Y] < .start_y || .@mob_data[UMOB_Y] > .end_y) ) { unitstopwalk(.@mobs[.@i], USW_FORCE_STOP); getfreecell(.map$, .@x, .@y, .center_x, .center_y, .range_x, .range_y); unitwalk(.@mobs[.@i], .@x, .@y); } } sleep(.check_interval); } freeloop(0); } Simply set the map, center coordinates and range for the area you want the mobs to be able to move in. Once they step outside the area, they will stop and walk back into it.
  21. Those stats aren't enchantments, those are random options. Those are groups of bonuses of which a specified amount gets picked randomly and added to an item on drop. For further explanation you can check item_randomopt_db.yml, item_randomopt_group.yml and mob_db.yml in the last you should check the RandomOptionGroup setting.
  22. 1. I don't know how the status changes accumulate if you stack them. But I think it isn't hard for you to test that, simply choose a rate and use an item like bubble gum and check how it influences your rate. 2. If your server is configured to have the default rates, those would be 1x, when a player chooses low it would add a bonus of 100% so 2x, on mid 19900% or 20x etc. It is good that you asked, since I realized I made a mistake in the script above and could correct it.
  23. I didn't test it, but changing the overweight check macros in pc.hpp from: #define pc_is50overweight(sd) ( (sd)->weight * 100 >= (sd)->max_weight * battle_config.natural_heal_weight_rate ) #define pc_is70overweight(sd) ( (sd)->weight * 100 >= (sd)->max_weight * battle_config.natural_heal_weight_rate_renewal ) #define pc_is90overweight(sd) ( (sd)->weight * 10 >= (sd)->max_weight * 9 ) to: #define pc_is50overweight(sd) ( false ) #define pc_is70overweight(sd) ( false ) #define pc_is90overweight(sd) ( false ) should do what you want.
  24. It won't influence the individual rates. What he provides is more or less just a poll. I think there is no direct way to overwrite rates directly for an individual player. But what you could do is set the rates of your server to default and use status changes to give each player an exp and drop bonus according to his choice to basically get the effect of different rates. - script RateSelect -1,{ OnSetRate: OnPCLoginEvent: switch(individual_rate) { case 1: .@exp_rate_bonus = .low_rate_exp_bonus; .@drop_rate_bonus = .low_rate_drop_bonus; break; case 2: .@exp_rate_bonus = .mid_rate_exp_bonus; .@drop_rate_bonus = .mid_rate_drop_bonus; break; case 3: .@exp_rate_bonus = .high_rate_exp_bonus; .@drop_rate_bonus = .high_rate_drop_bonus; break; default: mes "Select your preferred server rate for this character."; mes "BE CAREFUL: YOU CAN'T CHANGE IT AFTERWARD!" individual_rate = select("Low Rate:Mid Rate:High Rate"); close2; goto OnSetRate; } sc_start SC_EXPBOOST, INFINITE_TICK, .@exp_rate_bonus, 10000, SCSTART_NOICON; sc_start SC_ITEMBOOST, INFINITE_TICK, .@drop_rate_bonus, 10000, SCSTART_NOICON; end; OnInit: .low_rate_exp_bonus = 100; .mid_rate_exp_bonus = 19900; .high_rate_exp_bonus = 199900; .low_rate_drop_bonus = 100; .mid_rate_drop_bonus = 19900; .high_rate_drop_bonus = 199900; }
×
×
  • Create New...