Jump to content

Kenpachi

Core Developers
  • Content Count

    204
  • Joined

  • Last visited

  • Days Won

    32

Posts posted by Kenpachi


  1. 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

     


  2. Hi.

     

    Quick'n'dirty:
     

    Spoiler
    
    prontera,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


  3. 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


  4. As promised over at Discord, a patch to extend getiteminfo() script command, to get an item's ID by its name:getiteminfo_extension.diff

     

    Spoiler
    
    diff --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


  5. Hi.

     

    If you're only working with equipped items, you can use the getequipid() script command to read the item's ID.

    Spoiler
    Quote

    *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 1

     

    Notice 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


  6. 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


  7. 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


  8. 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:

    Spoiler
    
    prontera,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


  9. 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


  10. 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


  11. pc_status_def_rate and mob_status_def_rate still exist in in conf/map/battle/status.conf.
    If you need pc_luk_status_def and mob_luk_status_def, I could probably write a patch for you, but have a look at the commit where they were removed and see @Ind's reasons to remove them.

     

     

    ~Kenpachi


  12. 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


  13. 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

×
×
  • Create New...

Important Information

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