-
Content Count
204 -
Joined
-
Last visited
-
Days Won
32
Posts posted by Kenpachi
-
-
Hi.
Just update your server to the latest release.
Alternatively you can apply this patch: 1e572d0bd99b2f1f2b6a29f0184c9fb28e0db655.patch
~Kenpachi
-
Hi.
Please don't revive dead topics if you just opened a similar one by yourself.
I answered in your topic.
~Kenpachi
-
Hi.
-
Quote
How can I put CAP Resistance to a Certain Race? Example instead of 100% resist, i will only cap it to 50% even he/she has equipment with 100% resist.
In src/map/status.c -> function status_calc_pc_() find this line (#3099 in current release):status->copy(&sd->battle_status, bstatus);
Add above (replace <your_race_here> with the race you want to modify):
#ifdef RENEWAL sd->race_tolerance[<your_race_here>] = max(sd->race_tolerance[<your_race_here>], 50); #else sd->subrace[<your_race_here>] = max(sd->subrace[<your_race_here>], 50); #endif
-
Quote
Same goes to Reflect Change (Physical and Magical Reflect) to cap the limit only 50%
In src/map/pc.c -> function pc_bonus() find this block:
case SP_SHORT_WEAPON_DAMAGE_RETURN: if(sd->state.lr_flag != 2) sd->bonus.short_weapon_damage_return += val; break; case SP_LONG_WEAPON_DAMAGE_RETURN: if(sd->state.lr_flag != 2) sd->bonus.long_weapon_damage_return += val; break; case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here if(sd->state.lr_flag != 2) sd->bonus.magic_damage_return += val; break;
Replace it with:
case SP_SHORT_WEAPON_DAMAGE_RETURN: if (sd->state.lr_flag != 2) sd->bonus.short_weapon_damage_return += val; sd->bonus.short_weapon_damage_return = max(sd->bonus.short_weapon_damage_return, 50); break; case SP_LONG_WEAPON_DAMAGE_RETURN: if (sd->state.lr_flag != 2) sd->bonus.long_weapon_damage_return += val; sd->bonus.long_weapon_damage_return = max(sd->bonus.long_weapon_damage_return, 50); break; case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here if (sd->state.lr_flag != 2) sd->bonus.magic_damage_return += val; sd->bonus.magic_damage_return = max(sd->bonus.magic_damage_return, 50); break;
-
Quote
For Skill Delay, how can I set a general after cast delay cap to 50% (even he/she has equipment with 100% after cast delay, only 50% will apply due to capping.)
In src/map/status.c -> function status_calc_pc_() find this block:
//Underflow protections. if(sd->dsprate < 0) sd->dsprate = 0; if(sd->castrate < 0) sd->castrate = 0; if(sd->delayrate < 0) sd->delayrate = 0; if(sd->hprecov_rate < 0) sd->hprecov_rate = 0; if(sd->sprecov_rate < 0) sd->sprecov_rate = 0;
Add below:
sd->delayrate = max(sd->delayrate, 50);
Don't forget to re-compile. 😉
~Kenpachi -
-
Hi.
Quick'n'dirty:
Spoilerprontera,150,170,0 script Coin Exchange 4_F_KAFRA5,{ mes(.npc_name$); mes("What do you want to exchange for 1 Gold Coin?"); .@selection1 = select(.menu_option1$, .menu_option2$, .menu_option3$); mesclear(); mes(.npc_name$); if (countitem(Silver_Coin) < 1) { mes("You need at least 1 Silver Coin."); close(); } switch (.@selection1) { case 1: if (Zeny < 500) { mes("You need at least 500z."); close(); } break; case 2: if (#CASHPOINTS < 10) { mes("You need at least 10 Cash Points."); close(); } break; case 3: if (countitem(Poring_Coin) < 1) { mes("You need at least 1 Poring Coin."); close(); } break; } mes("Are you sure?"); .@selection2 = select("Yes", "No"); mesclear(); mes(.npc_name$); if (.@selection2 == 2) { mes("Okay, see you."); close(); } delitem(Silver_Coin, 1); switch (.@selection1) { case 1: // 20% success chance. .@failed = (rand(10000) < 8000) ? 1 : 0; Zeny -= 500; break; case 2: // 50% success chance. .@failed = (rand(10000) < 5000) ? 1 : 0; #CASHPOINTS -= 10; break; case 3: // 90% success chance. .@failed = (rand(10000) < 1000) ? 1 : 0; delitem(Poring_Coin, 1); break; } if (.@failed == 1) { mes("Sorry, you had no luck."); } else { mes("You're a lucky person and obtain 1 Gold Coin."); getitem(Gold_Coin, 1); } close(); OnInit: .npc_name$ = "[" + strnpcinfo(NPC_NAME_VISIBLE) + "]"; .menu_option1$ = "1 Silver Coin + 500z (20% chance)"; .menu_option2$ = "1 Silver Coin + 10 Cash Points (50% chance)"; .menu_option3$ = "1 Silver Coin + 1 Poring Coin (90% chance)"; end; }
~Kenpachi
hadiesyafiq reacted to this -
Hi.
if (rand(10000) < 2000) // 20% chance to fail. // FAIL else // SUCCESS
~Kenpachi
-
-
Hercules uses libconfig based database files.
Since you're using rAthena, please get support there.
~Kenpachi
-
I can't reproduce this with latest server version.
Which version is your server? (In the map-server console find [Info]: Git revision (src):)
Which client do you use?
Any modifications to the server?
~Kenpachi
-
For the skill use event, there is a plugin (with additional features):
Maybe it needs a little fixing, tho.
~Kenpachi
-
-
Hi.
The error is caused by something trying to set a skills name. (Type 64 = BL_SKILL)
As far as I can tell, this can only happen in setunittitle() script command or setunitdata() script command (type = UDT_GROUP), because those two script commands don't verify the BL type.
Do you have custom scripts which use these script commands?
If not, can you re-produce this error and tell us how?
~Kenpachi
-
As promised over at Discord, a patch to extend getiteminfo() script command, to get an item's ID by its name:getiteminfo_extension.diff
Spoilerdiff --git a/doc/script_commands.txt b/doc/script_commands.txt index 8308f4771..e24c6b1d4 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3277,6 +3277,7 @@ Example: --------------------------------------- *getiteminfo(<item ID>, <type>) +*getiteminfo("<item name>", <type>) *setiteminfo(<item ID>, <type>, <value>) This function will look up the item with the specified ID number in the @@ -3285,6 +3286,9 @@ It will return -1 if there is no such item. Valid types are: + ITEMINFO_ID - Item ID (getiteminfo() only!) + ITEMINFO_AEGISNAME - Unique name to reference the item (getiteminfo() only!) + ITEMINFO_NAME - Display name (getiteminfo() only!) ITEMINFO_BUYPRICE - Buy Price ITEMINFO_SELLPRICE - Sell Price ITEMINFO_TYPE - Item Type diff --git a/src/map/script.c b/src/map/script.c index c1eb2e8b7..4c485ec28 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14788,9 +14788,15 @@ static BUILDIN(getitemslots) *------------------------------------------*/ static BUILDIN(getiteminfo) { - int item_id = script_getnum(st, 2); int n = script_getnum(st, 3); - struct item_data *it = itemdb->exists(item_id); + struct item_data *it; + + if (script_isstringtype(st, 2)) { /// Item name. + const char *name = script_getstr(st, 2); + it = itemdb->search_name(name); + } else { /// Item ID. + it = itemdb->exists(script_getnum(st, 2)); + } if (it == NULL) { script_pushint(st, -1); @@ -14928,6 +14934,15 @@ static BUILDIN(getiteminfo) case ITEMINFO_GM_LV_TRADE_OVERRIDE: script_pushint(st, it->gm_lv_trade_override); break; + case ITEMINFO_ID: + script_pushint(st, it->nameid); + break; + case ITEMINFO_AEGISNAME: + script_pushstr(st, it->name); + break; + case ITEMINFO_NAME: + script_pushstr(st, it->jname); + break; default: ShowError("buildin_getiteminfo: Invalid item type %d.\n", n); script_pushint(st,-1); @@ -26970,7 +26985,7 @@ static void script_parse_builtin(void) BUILDIN_DEF(setnpcdisplay,"sv??"), BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. BUILDIN_DEF(strcmp,"ss"), - BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info + BUILDIN_DEF(getiteminfo,"vi"), //[Lupus] returns Items Buy / sell Price, etc info BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item BUILDIN_DEF(getequippedoptioninfo, "i"), @@ -27615,6 +27630,9 @@ static void script_hardcoded_constants(void) script->set_constant("ITEMINFO_ITEM_USAGE_FLAG", ITEMINFO_ITEM_USAGE_FLAG, false, false); script->set_constant("ITEMINFO_ITEM_USAGE_OVERRIDE", ITEMINFO_ITEM_USAGE_OVERRIDE, false, false); script->set_constant("ITEMINFO_GM_LV_TRADE_OVERRIDE", ITEMINFO_GM_LV_TRADE_OVERRIDE, false, false); + script->set_constant("ITEMINFO_ID", ITEMINFO_ID, false, false); + script->set_constant("ITEMINFO_AEGISNAME", ITEMINFO_AEGISNAME, false, false); + script->set_constant("ITEMINFO_NAME", ITEMINFO_NAME, false, false); script->constdb_comment("getmercinfo options"); script->set_constant("MERCINFO_ID,", MERCINFO_ID, false, false); diff --git a/src/map/script.h b/src/map/script.h index 857d22c61..ed860368c 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -484,6 +484,9 @@ enum script_iteminfo_types { ITEMINFO_ITEM_USAGE_FLAG, ITEMINFO_ITEM_USAGE_OVERRIDE, ITEMINFO_GM_LV_TRADE_OVERRIDE, + ITEMINFO_ID, + ITEMINFO_AEGISNAME, + ITEMINFO_NAME, ITEMINFO_MAX };
Usage:
.@item_id = getiteminfo("item name", ITEMINFO_ID);
~Kenpachi
-
Hi.
If you're only working with equipped items, you can use the getequipid() script command to read the item's ID.
SpoilerQuote*getequipid(<equipment slot>)
This function returns the item ID of the item equipped in the equipment
slot specified on the invoking character. If nothing is equipped there, it
returns -1. Valid equipment slots are:EQI_HEAD_TOP (1) - Upper head gear
EQI_ARMOR (2) - Armor (Where you keep your Jackets and Robes)
EQI_HAND_L (3) - What is in your Left hand.
EQI_HAND_R (4) - What is in your Right hand.
EQI_GARMENT (5) - The garment slot (Mufflers, Hoods, Manteaus)
EQI_SHOES (6) - What foot gear the player has on.
EQI_ACC_L (7) - Accessory 1.
EQI_ACC_R (8) - Accessory 2.
EQI_HEAD_MID (9) - Middle Headgear (masks and glasses)
EQI_HEAD_LOW (10) - Lower Headgear (beards, some masks)
EQI_COSTUME_HEAD_LOW (11) - Lower Costume Headgear
EQI_COSTUME_HEAD_MID (12) - Middle Costume Headgear
EQI_COSTUME_HEAD_TOP (13) - Upper Costume Headgear
EQI_COSTUME_GARMENT (14) - Costume Garment
EQI_SHADOW_ARMOR (15) - Shadow Armor
EQI_SHADOW_WEAPON (16) - Shadow Weapon
EQI_SHADOW_SHIELD (17) - Shadow Shield
EQI_SHADOW_SHOES (18) - Shadow Shoes
EQI_SHADOW_ACC_R (19) - Shadow Accessory 2
EQI_SHADOW_ACC_L (20) - Shadow Accessory 1Notice that a few items occupy several equipment slots, and if the
character is wearing such an item, 'getequipid' will return it's ID number
for either slot.Can be used to check if you have something equipped, or if you haven't got
something equipped:if (getequipid(EQI_HEAD_TOP) == Tiara) { mes("What a lovely Tiara you have on"); close(); } mes("Come back when you have a Tiara on"); close();
You can also use it to make sure people don't pass a point before removing
an item totally from them. Let's say you don't want people to wear Legion
Plate armor, but also don't want them to equip if after the check, you
would do this:if (getequipid(EQI_ARMOR) == Full_Plate_Armor || getequipid(EQI_ARMOR) == Full_Plate_Armor_) { mes("You are wearing some Legion Plate Armor, please drop that in your stash before continuing"); close(); } if (countitem(Full_Plate_Armor) > 0 || countitem(Full_Plate_Armor_) > 0) { mes("You have some Legion Plate Armor in your inventory, please drop that in your stash before continuing"); close(); } mes("I will lets you pass"); close2(); warp("place", 50, 50); end;
But there's no script command to generally get an item's ID from its name.
~Kenpachi
-
Hi.
You can either forward the server ports in your router to the computer where the server runs on, or you can use tools like Hamachi to create a VPN.
You should find many explanations/guides on google for both methods.
~Kenpachi
-
Hi.
In src/map/skill.c find function skill_get_requirement() and replace: (Should be line 15479.)
if (itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN) {
with:
if (itemid_isgemstone(req.itemid[i]) && sd->group->level >= 99) { /// Characters with group level >= 99 don't use gemstones. req.itemid[i] = 0; req.amount[i] = 0; } else if (itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN) {
Or use this diff: ADMIN_NO_GEMS.diff
I tested this modification with latest Hercules and it works.
~Kenpachi
-
Hi.
Maybe a little bit late, but...
You can disguise a player with the changelook() script command. Just use an item's OnEquipScript/OnUnequipScript.
An example to disguise the player as Swordman when equipping Hat.
{ Id: 2220 AegisName: "Hat" Name: "Hat" Type: "IT_ARMOR" Buy: 1000 Weight: 200 Def: 2 Loc: "EQP_HEAD_TOP" ViewSprite: 16 OnEquipScript: <" changelook(LOOK_BASE, Job_Swordman); "> OnUnequipScript: <" changelook(LOOK_BASE, Class); "> }
But this works only with jobs. If you have custom body sprites, you have to add them as new jobs.
~Kenpachi
-
Hi.
That tool isn't even close to be compatible with Hercules, since it's designed for Cronus. Please don't use it.
Here is a syntax-fixed version of your script:
Spoilerprontera,160,181,4 script Newton 4W_M_03,{ mes("[Newton]"); mesf("Hello %s!", strcharinfo(PC_NAME)); mes("I have some interesting items here, would you like to take a look?"); next(); if (select("Sure!:Maybe later ...") == 2) { mes("[Newton]"); mes("Alright, I'll be here if you change your mind."); close(); } mes("[Newton]"); mes("Well, these are the items I have ..."); mes("Which one would you like to know more about?"); next(); switch (select("Leaf Warrior Hat:Leaf Wing:None")) { case 1: mes("[Leaf Warrior Hat]"); mes("Reward:"); mesf("1x %s", getitemname(40007)); mes(""); mes("Requirement:"); mesf("20x %s", getitemname(731)); mesf("5x %s", getitemname(732)); mesf("3x %s", getitemname(719)); mesf("3x %s", getitemname(720)); mesf("3x %s", getitemname(724)); mesf("3x %s", getitemname(721)); mesf("3x %s", getitemname(725)); mesf("3x %s", getitemname(727)); next(); mes("[Newton]"); mes("Do you want to do this quest?"); next(); if (select("Yes!:Not now ...") == 2) { mes("[Newton]"); mes("Alright ... See you later!"); close(); } if (countitem(731) >= 20 && countitem(732) >= 5 && countitem(719) >= 3 && countitem(720) >= 3 && countitem(724) >= 3 && countitem(721) >= 3 && countitem(725) >= 3 && countitem(727) >= 3) { delitem(731, 20); delitem(732, 5); delitem(719, 3); delitem(720, 3); delitem(724, 3); delitem(721, 3); delitem(725, 3); delitem(727, 3); getitem(40007, 1); mes("[Newton]"); mes("Congratulations! Here it is!"); close(); } break; case 2: mes("[Leaf Wing]"); mes("Reward:"); mesf("1x %s", getitemname(40006)); mes(""); mes("Requirement:"); mesf("100x %s", getitemname(511)); mesf("50x %s", getitemname(507)); mesf("50x %s", getitemname(508)); mesf("25x %s", getitemname(509)); mesf("10x %s", getitemname(521)); mesf("3x %s", getitemname(2270)); mesf("2x %s", getitemname(2207)); mesf("2x %s", getitemname(707)); mesf("1x %s", getitemname(706)); next(); mes("[Newton]"); mes("Do you want to do this quest?"); next(); if (select("Yes!:Not now ...") == 2) { mes("[Newton]"); mes("Alright ... See you later!"); close(); } if (countitem(511) >= 100 && countitem(507) >= 50 && countitem(508) >= 50 && countitem(509) >= 25 && countitem(521) >= 10 && countitem(2270) >= 3 && countitem(2207) >= 2 && countitem(707) >= 2 && countitem(706) >= 1) { delitem(511, 100); delitem(507, 50); delitem(508, 50); delitem(509, 25); delitem(521, 10); delitem(2270, 3); delitem(2207, 2); delitem(707, 2); delitem(706, 1); getitem(40006, 1); mes("[Newton]"); mes("Congratulations! Here it is!"); close(); } break; case 3: mes("[Newton]"); mes("Alright, I'll be here if you change your mind."); close(); } mes("[Newton]"); mes("I'm sorry, but you don't have all the items needed for this quest."); mes("Come back when you have all the items!"); close(); }
~Kenpachi
-
Nope. That script command just enables you to check if the character is walking or not.
You can use it to prevent that freeze you mentioned. Your script may could look like this, after you added the script command to your source:
izlude,124,148,4 script test#iz 4_F_NURSE,{ .@GID = getcharid(3); unitwalk .@GID,128,124; while (unitiswalking(.@GID) == 1) sleep2(50); unitwalk .@GID,128,109; while (unitiswalking(.@GID) == 1) sleep2(50); unitwalk .@GID,121,98; while (unitiswalking(.@GID) == 1) sleep2(50); unitwalk .@GID,108,97; end; }
~Kenpachi
-
Unfortunately the script engine currently provides no command to check if a character is walking or not.
Guess you have to play with the sleep times a bit.
//EDIT:
I wrote a script command to check if a unit is walking: https://github.com/HerculesWS/Hercules/pull/2628
You may add it by yourself, or wait until the PR is merged.
~Kenpachi
-
Hi.
From doc/script_commands.txt
*unitwalk(<GID>, <x>, <y>) *unitwalk(<GID>, <target_GID>) This is one command, but can be used in two ways. If only the first argument is given, the unit whose GID is given will start walking towards the target whose GID is given. When 2 arguments are passed, the given unit will walk to the given x,y coordinates on the map where the unit currently is. Examples: //Will move/walk the poring we made to the coordinates 150,150 unitwalk(.GID, 150, 150); //NPC will move towards the attached player. unitwalk(.GID, getcharid(CHAR_ID_ACCOUNT));//a player's GID is their account ID
.GID is the character's account ID.
~Kenpachi
-
Hello.
Please provide information about what you did exactly. (Item DB entries and client data entries.)
Moved the topic to General Server Support section.
~Kenpachi
-
-
Indeed. But the permission flag skill_unconditional makes all conditions being ignored. From skill.c skillnotok():
if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) return 0; // can do any damn thing they want
And because @brunosc explicitly asked for gemstones, I wrote that dirty little hack. 😅
~Kenpachi
-
Hi.
Quick, dirty and untested:admin_no_gems.diff
diff --git a/src/map/pc.c b/src/map/pc.c index 179a4b78a..c77bfbc22 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1359,6 +1359,10 @@ static bool pc_authok(struct map_session_data *sd, int login_id2, time_t expirat sd->sc_display = NULL; sd->sc_display_count = 0; + /// Characters with group level => 99 don't use gemstones. + if (sd->group->level >= 99) + sd->special_state.no_gemstone = 1; + // Request all registries (auth is considered completed whence they arrive) intif->request_registry(sd,7); return true;
~Kenpachi
Alter formula bonus2 bAddClass,Class_All
in Source Support
Posted
Hi.
There is neither a bonus called bAddClass nor a constant called Class_All in Hercules.
~Kenpachi