Jump to content

Talis

Members
  • Posts

    7
  • Joined

  • Last visited

Posts posted by Talis

  1. 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;
                    }
    
    • Upvote 1
  2. 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;
    }
    
  3. 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?

    • Upvote 1
  4. 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!

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

    Click here to download this file

×
×
  • Create New...