Talis
-
Posts
7 -
Joined
-
Last visited
Content Type
Profiles
Forums
Downloads
Jobs Available
Server Database
Third-Party Services
Top Guides
Store
Crowdfunding
Posts posted by Talis
-
-
The relevant source block in battle.c:
else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) ) { if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) ) return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. else return 0; // You can't target anything out of your duel }
If the only thing you replaced is
else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) ) into else if(( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg&& map_flag_gvg(m))))||( cell_pk_check(t_bl, s_bl, m) == true ))
Then it's no wonder that it's not working.
Look at the line right below:
if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) )
That translates to "If the target is a player AND targets duel_group matches mine"
I would say just make a extra if / else, like so:
case BL_PC: { struct map_session_data *sd = BL_CAST(BL_PC, s_bl); if( s_bl != t_bl ) { if( sd->state.killer ) { state |= BCT_ENEMY; // Can kill anything strip_enemy = 0; } else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) ) { if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) ) return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. else return 0; // You can't target anything out of your duel } else if( cell_pk_check(t_bl, s_bl, m) == true ) { return (BCT_ENEMY&flag)?1:-1; } } if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->class_ == MOBID_EMPERIUM ) return 0; //If you don't belong to a guild, can't target emperium. if( t_bl->type != BL_PC ) state |= BCT_ENEMY; //Natural enemy. break; }
- 1
-
You need a else between the first if and the second if.
Right now, you check if the killed monster gives MVP EXP ( only true for MVPs ), then afterwards you separately check whether the mob has the boss flag ( true for both proper MVPs and mini bosses ).
For MVP drop item 1, mini boss drop item 2, use:
- script mvpkill -1,{ OnNPCKillEvent: if ( getmonsterinfo( killedrid, MOB_MVPEXP ) && rand(100) < 20 ) { if ( getcharid(1) ) { getpartymember getcharid(1), 1; getpartymember getcharid(1), 2; for ( .@i = 0; .@i < $@partymembercount; .@i++ ) { if ( isloggedin( $@partymemberaid[.@i], $@partymembercid[.@i] ) ) { // what happens if someone in the party member is offline =/ .@partymemberaid[.@c] = $@partymemberaid[.@i]; .@c++; } } getitem 8400, 2, .@partymemberaid[ rand( .@c ) ]; announce "Player ["+ strcharinfo(0) +"] of ["+ strcharinfo(1) +"] party has killed "+ getmonsterinfo( killedrid, MOB_NAME ) +" at "+ strcharinfo(3), 0; } else { getitem 8400, 2; announce "Player ["+ strcharinfo(0) +"] has killed "+ getmonsterinfo( killedrid, MOB_NAME ) +" at "+ strcharinfo(3), 0; } } else if( getmonsterinfo(killedrid, 21) & 0x0020 && rand(100) < 20 ) { if ( getcharid(1) ) { getpartymember getcharid(1), 1; getpartymember getcharid(1), 2; for ( .@i = 0; .@i < $@partymembercount; .@i++ ) { if ( isloggedin( $@partymemberaid[.@i], $@partymembercid[.@i] ) ) { // what happens if someone in the party member is offline =/ .@partymemberaid[.@c] = $@partymemberaid[.@i]; .@c++; } } getitem 8404, 1, .@partymemberaid[ rand( .@c ) ]; announce "You have received an item by killing "+ getmonsterinfo( killedrid, MOB_NAME ) +" .", bc_self; } else { getitem 8404, 1; announce "You have received an item by killing "+ getmonsterinfo( killedrid, MOB_NAME ) +" .", bc_self; } } end; }
If you want ONLY mini bosses:
- script mvpkill -1,{ OnNPCKillEvent: if ( !getmonsterinfo( killedrid, MOB_MVPEXP ) && getmonsterinfo(killedrid, 21) & 0x0020 && rand(100) < 20 ) { if ( getcharid(1) ) { getpartymember getcharid(1), 1; getpartymember getcharid(1), 2; for ( .@i = 0; .@i < $@partymembercount; .@i++ ) { if ( isloggedin( $@partymemberaid[.@i], $@partymembercid[.@i] ) ) { // what happens if someone in the party member is offline =/ .@partymemberaid[.@c] = $@partymemberaid[.@i]; .@c++; } } getitem 8400, 2, .@partymemberaid[ rand( .@c ) ]; announce "Player ["+ strcharinfo(0) +"] of ["+ strcharinfo(1) +"] party has killed "+ getmonsterinfo( killedrid, MOB_NAME ) +" at "+ strcharinfo(3), 0; } else { getitem 8400, 2; announce "Player ["+ strcharinfo(0) +"] has killed "+ getmonsterinfo( killedrid, MOB_NAME ) +" at "+ strcharinfo(3), 0; } } end; }
-
The only announcement / mention on the boards is here:
http://rathena.org/board/topic/87083-julyaugust-digest/?hl=a4fdc72#
This might not be 100% accurate since I'm new here and havn't worked with the system, but the gist is:
Putting source mods directly into the .c files, such as script.c and atcommands.c is messy, because it can make revision updates troublesome - often leading to manually having to merge together your custom file and the new server revision file.
The custom folder contains script.inc, script_def.inc, atcommand.inc and atcommand_def.inc.
The main part of a script ( BUILDIN_FUNC(command) ) goes into custom/script.inc
The definition of a script ( BUILDIN_DEF(command, parameters) ) goes into custom/script_def.inc
The main part of a atcommand ( ACMD_FUNC(command) ) goes into custom/atcommand.inc
The definition of a atcommand ( { "command", gmlevel,gmlevel, atcommand_command } ) goes into custom/atcommand_def.inc
This keeps things organized, and your main eAthena source code clean, allowing for painless revision updates.
Does that clear it up?
- 1
-
Perhaps you might not mind placing the command in src/custom/script.inc and script_def.inc?
Example: http://rathena.org/board/topic/88908-script-command-getrandmob/
Just trying to push people to use what's available.
Hey,
I hope I won't be stepping on anyones toes, but I actually dev on a pretty customized version of eAthena, which doesn't have that functionality, else I would definitely make use of it.
Looking at the example you linked, it should be really easy actually for people to make use of the custom folder functionality. I didn't provide diffs, just raw source, so the only thing that changes is where you copy & paste it to, right?
Hm .. I might put up a new zip file soon where I mention that it can be put either in script.c or in script.inc
So.. If you have the custom folder, throw it in the script.inc and script_def.inc instead of directly into script.c!
-
File Name: Script command: Dynprompt
File Submitter: Talis
File Submitted: 08 Nov 2013
File Category: Source Modifications
Content Author: Talis
Works like prompt(), but lets you specify return values by adding a pipe symbol.
Examples:
dynprompt("Menu Entry");
Return Value: 1
@menu: 1
@menustr$: Menu Entry
@menunum: 1
dynprompt("^EE0000Menu Entry^000000|Test");
Return Value: 1
@menu: 1
@menustr$: Test
@menunum: 1
dynprompt("Shazam|5 Shazam");
Return Value: 5
@menu: 1
@menustr$: 5 Shazam
@menunum: 5
Script example:
// Dynprompt usage - Advanced example// Probably the best way to use thisfunction script dynprompt_sample3 { // The real power of dynprompt is that you can specify the return value for each menu element. // The return value is a atoi of the string following the pipe | - the full string can be accessed through @menustr$ // The atoi val can also be accessed through @menunum // If you want to use both number & string, the number has to come first else atoi won't work // Use the pipe character | to denote the return value - best to work with numbers, but strings work as well set .@menu$[0], "^009900Hello!^000000|1Hello"; set .@menu$[1], "^0000EEInfo~^000000|2Info"; set .@menu$[2], "^222222Test.^000000|3Test"; // This time we'll just add a element based on a condition if(.@somecondition) set .@menu$[3], "^EE0000- Admin -^000000|4Admin"; set .@menu$[4], "^990099G'bye^000000|5Bye"; // Lets implode & switch/case switch(dynprompt(implode(.@menu$, ":"))) { case 1: mes "Oh, Hello to you too!"; break; case 2: mes "You want info? How about the time?"; mes gettimestr("%Y-%m/%d %H:%M:%S",21); mes "Also, you selected option #" + @menu; // @menu still works break; case 3: mes "Debug info:"; mes "@menu is " + @menu; mes "@menustr$ is " + @menustr$; mes "@menunum is " + @menunum; break; case 4: mes "Wow, a admin!"; break; case 5: mes "Bye bye~"; break; case 255: // Cancel button mes "Hey, don't ignore me!!"; break; } close;}
I havn't tested it yet in production, but so far I havn't been able to encounter any issues with it.
Also, I do all my eAthena devving on a windows box so I can't guarantee that it'll work with linux.
Performance of dynprompt is going to be naturally worse than prompt, select or menu, but it might perform equally well in a dynamic setting if you take into consideration the array looping usually required - but I have not yet done any benchmarking or anything, so don't take my word for it. ( and to be honest, being able to create super clean code using switch / case is worth a tiny performance hit for me )
I hope it will make your scripting less painful - it sure has for me!
delete_timer error HELP! im stuck!
in Source Support
Posted
Could you try reverting those changes one at a time to determine exactly what change it was that introduced this error? Cause I feel that trying to debug it with the information you provided would be akin to finding a needle in a haystack.