OnPCStatCalcEvent

AnnieRuru

~~Cute~Cute~Scripter~~
Messages
1,677
Points
0
Location
your next door ~
Discord
AnnieRuru#1609
Github
AnnieRuru
Emulator
Client Version
2019-05-30aRagexeRE
rathena already has this by default -> https://github.com/rathena/rathena/commit/27a0f3f
someone else has tried to pull request in hercules, -> https://github.com/HerculesWS/Hercules/pull/351
but it was denied, so have to leave this as plugin

UPDATE: rathena has taken out -> https://github.com/rathena/rathena/commit/b65443d8f564175196d57ef9bc1d000a5661fbdc

Download : 2.1
plugin

Tested with:

conf\import\OnPCStatCalcEvent.conf

both `@reloadscript` and `@reloadonpcstatcalcevent` command can reload conf\import\OnPCStatCalcEvent.conf file 

`@reloadscript` = reload everything -> cause destruction on live server

`@reloadonpcstatcalcevent` = only reload conf\import\OnPCStatCalcEvent.conf file , combine with `@reloadnpc` command -> not so destructive

script: (
{ // give GM permanent bonus ?
OnPCStatCalcEvent:
<"
bonus bVit, 1234;
end;
">
},

{ // for xxx event
OnPCStatCalcEvent:
<"
skill TF_HIDING, 1;
end;
">
},

{ // npc/custom/xxxevent.txt
OnPCStatCalcEvent:
<"
if (@a) {
bonus bStr, 1000;
skill WZ_ICEWALL, 1;
}
end;
">
},

)


script

prontera,158,185,5 script djk2sfhsd 1_F_MARIA,{
@a ^= 1;
mes "hmm...";
recalculatestat();
next;
mes "what ?";
@a ^= 1;
recalculatestat();
next;
mes "maybe...";
@a ^= 1;
recalculatestat();
next;
mes "probably...";
@a ^= 1;
recalculatestat();
next;
mes "yeah...";
@a ^= 1;
recalculatestat();
close;
}


yes, this actually works !!

with version 2.0 onwards,

no more spamming <npc name>::OnPCStatCalcEvent !!

and even `*skill` working perfectly fine now

1.0 - plugin

1.1 - plugin
- found a way to get *recalculatestat working, although its not thread-safe, but meh ~

1.2 - plugin
- remove some nullpo

1.3 - plugin

- update to latest hercules revision

2.0 - plugin

- overhaul the way how to give player permanent bonus, now no more using npc label, but using an external file

- fix `*skill` doesn't work correctly previously

- `*recalculatestat` no longer using addtimer hack

- no more spamming "<npc name>::OnPCStatCalcEvent" anymore !!! yes tested !!

2.1 - plugin

- add `@reloadonpcstatcalcevent` to safely reload only OnPCStatCalcEvent.conf file without using the destructive `@reloadscript`

 
Last edited by a moderator:
if got warning about queue is full , it's had a bad affect to our server ? or just showing warning

 
Annie is gone, so I was in doubt about where to post, but here it is.
 
Note: I updated the plugin for the latest version of hercules.
//===== Hercules Plugin ======================================
//= OnPCStatCalcEvent
//===== By: ==================================================
//= AnnieRuru
//= originally by QQfoolsorellina
//===== Current Version: =====================================
//= 1.0
//===== Compatible With: =====================================
//= Hercules 2015-11-29
//===== Description: =========================================
//= give player permanent bonus
//===== Topic ================================================
//= http://herc.ws/board/topic/11292-onpcstatcalcevent/
//===== Additional Comments: =================================
//= stat_recalc script command doesn't really work, I dunno why
//============================================================


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "common/hercules.h"
#include "map/pc.h"
#include "map/npc.h"
//#include "map/script.h"
#include "map/status.h"
#include "common/nullpo.h"
#include "plugins/HPMHooking.h"
#include "common/HPMDataCheck.h"

HPExport struct hplugin_info pinfo = {
"OnPCStatCalcEvent", // Plugin name
SERVER_TYPE_MAP,// Which server types this plugin works with?
"1.0", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};

void status_calc_pc_additional_pre( struct map_session_data *sd, enum e_status_calc_opt *opt ) {
nullpo_retv(sd);
npc->event_doall_id( "OnPCStatCalcEvent", sd->bl.id );
return;
}

/* this stupid command doesn't work
BUILDIN(stat_recalc) {
TBL_PC* sd;
if ( script_hasdata(st,2) ) {
if ( data_isstring( script_getdata(st,2) ) )
sd = map->nick2sd( script_getstr(st,2) );
else
sd = map->id2sd( script_getnum(st,2) );
} else
sd = script->rid2sd(st);
if (sd) {
// status_calc_pc(sd, SCO_NONE);
// status->calc_pc_(sd, SCO_NONE);
// status->calc_pc_(sd, SCO_FORCE);
status_calc_pc(sd, SCO_FORCE);
ShowDebug( "run" );
}
return true;
}
*/
HPExport void plugin_init (void) {
addHookPre(status, calc_pc_additional, status_calc_pc_additional_pre );
// addScriptCommand( "stat_recalc", "?", stat_recalc );
}

Errors:

Code:
[Error]: --- nullpo info --------------------------------------------
[Error]: hercules\src\map\npc.c:841: 'sd' in function `unknown'
[Error]: --- end nullpo info ----------------------------------------
[Error]: --- nullpo info --------------------------------------------
[Error]: hercules\src\map\npc.c:841: 'sd' in function `unknown'
[Error]: --- end nullpo info ----------------------------------------
[Error]: --- nullpo info --------------------------------------------
[Error]: hercules\src\map\npc.c:841: 'sd' in function `unknown'
[Error]: --- end nullpo info ----------------------------------------
[Error]: --- nullpo info --------------------------------------------
[Error]: hercules\src\map\npc.c:841: 'sd' in function `unknown'
[Error]: --- end nullpo info ----------------------------------------
 
1.1
plugin
- found a way to get *recalculatestat working, although its not thread-safe, but meh ~

 
Found an issue. Console getting spammed with this:

Code:
[Mar/29 14:50:41][Warning]: npc_event: player's event queue is full, can't add event 'RecalcStat::OnPCStatCalcEvent' !
 
Found an issue. Console getting spammed with this:

Code:
[Mar/29 14:50:41][Warning]: npc_event: player's event queue is full, can't add event 'RecalcStat::OnPCStatCalcEvent' !
this isn't an issue, it just say it runs this event too many times
probably having some scripts runs jobchange + statusup +equip + .... etc stuffs

I remember you said something about having a refiner script runs in loop ... probably caused by that
and even that ... it shouldn't effect anything ... just an error message

 
Last edited by a moderator:
@AnnieRuru I tried to work with more unsuccessful consumables

where am i going wrong?

Item:

{
Id: 32247
AegisName: "Dark_Elf_Potion"
Name: "Dark Elf Potion"
Type: "IT_USABLE"
Weight: 100
BuyingStore: true
Trade: {
nodrop: true
noselltonpc: true
nomail: true
noauction: true
}
Script: <" callfunc "Dark_Elf"; ">
},


Function:

Code:
function	script	Dark_Elf	{

@a ^= 1;
recalculatestat(); // if player under a dialog, MUST use close2; then only recalculate

OnPCStatCalcEvent:
	if ( @a )
		bonus bDex, 10;
		bonus bInt, 20;
		bonus bAgi, 5;
		bonus bMatk, 100;
	end;

}
 
update to version 1.3

plugin

@AnnieRuru I tried to work with more unsuccessful consumables

where am i going wrong?
consumables should be done with *sc_start something

{
Id: 32247
AegisName: "Dark_Elf_Potion"
Name: "Dark Elf Potion"
Type: "IT_USABLE"
Weight: 100
BuyingStore: true
Trade: {
nodrop: true
noselltonpc: true
nomail: true
noauction: true
}
Script: <"
sc_start SC_INCDEX, 500, 10;
sc_start SC_INCINT, 500, 20;
sc_start SC_INCAGI, 500, 5;
sc_start SC_INCMATKRATE, 500, 10;
">
},


seems unrelated to what this modification does ... though

 
2.0 - plugin

- overhaul the way how to give player permanent bonus, now no more using npc label, but using an external file

- fix `*skill` doesn't work correctly previously

- `*recalculatestat` no longer using addtimer hack

- no more spamming "<npc name>::OnPCStatCalcEvent" anymore !!! yes tested !!

as like before, `@reloadscript` command can reload conf\import\OnPCStatCalcEvent.conf file



and if you guys didn't know, rAthena removed OnPCStatCalcEvent !!! MUAHAHAHA !!!

https://github.com/rathena/rathena/commit/b65443d8f564175196d57ef9bc1d000a5661fbdc

why cause headache ? I just live with it

https://github.com/rathena/rathena/issues/4812

cast blessing will make OnPCStatCalcEvent bonus disappear ?

I just tested on version 2.0, no problem :hum:



2.1 - plugin

- add `@reloadonpcstatcalcevent` to safely reload only OnPCStatCalcEvent.conf file without using the destructive `@reloadscript`

 
Last edited by a moderator:
script: ( { // give GM permanent bonus ? OnPCStatCalcEvent: <" bonus bVit, 1234; end; "> }, { // for xxx event OnPCStatCalcEvent: <" skill TF_HIDING, 1; end; "> }, { // npc/custom/xxxevent.txt OnPCStatCalcEvent: <" if (@a) { bonus bStr, 1000; skill WZ_ICEWALL, 1; } end; "> }, )
Is there still support on this? How do i access them separately? let's say i decalred 3 OnPCStatCalcEvent here and i need 1 npc to just access 3 of those 6? 

 
nvm, I fixed mine.

hello can anyone help me decode which part when I relogin/logout the OnPCStatCalcEvent bonus stats disappear? I want to turn that off.

Code:
//===== Hercules Plugin ======================================
//= OnPCStatCalcEvent
//===== By: ==================================================
//= AnnieRuru
//= originally by QQfoolsorellina
//===== Current Version: =====================================
//= 2.0
//===== Compatible With: ===================================== 
//= Hercules 2020-11-12
//===== Description: =========================================
//= give player permanent bonus
//===== Topic ================================================
//= http://herc.ws/board/topic/11292-onpcstatcalcevent/
//===== Additional Comments: =================================  
//= fix `*skill` doesn't work correctly by using an external file
//============================================================

#include "common/hercules.h"
#include "map/pc.h"
#include "map/script.h"
#include "map/status.h"
#include "common/conf.h"
#include "common/memmgr.h"
#include "plugins/HPMHooking.h"
#include "common/HPMDataCheck.h"

HPExport struct hplugin_info pinfo = {
	"OnPCStatCalcEvent",
	SERVER_TYPE_MAP,
	"2.0",
	HPM_VERSION,
};

VECTOR_DECL(struct script_code *)statcalcevent;

int read_onpcstatcalcevent(void) {
	const char *confpath = "conf/import/OnPCStatCalcEvent.conf";
	struct config_t onpcstatcalcevent_conf;
	if (!libconfig->load_file(&onpcstatcalcevent_conf, confpath)) {
		ShowError("can't read %s, file not found !\n", confpath);
		return -1;
	}

	struct config_setting_t *config_db = libconfig->setting_get_member(onpcstatcalcevent_conf.root, "script");
	if (config_db == NULL) {
		ShowError("can't read %s\n", confpath);
		libconfig->destroy(&onpcstatcalcevent_conf);
		return -1;
	}

	struct config_setting_t *config = NULL;
	int i = 0;
	struct script_code *tmp;
	const char *string = NULL;
	VECTOR_INIT(statcalcevent);
	while ((config = libconfig->setting_get_elem(config_db, i++))) {
		if (libconfig->setting_lookup_string(config, "OnPCStatCalcEvent", &string)) {
			tmp = script->parse(string, "OnPCStatCalcEvent", 0, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL);
			VECTOR_ENSURE(statcalcevent, 1, 1);
			VECTOR_PUSH(statcalcevent, tmp);
		}
		else
			ShowError("Invalid Type on entry no."CL_WHITE"%d"CL_RESET" in '"CL_WHITE"%s"CL_RESET"'.\n", i, confpath);
	}

//	ShowDebug("%d\n", VECTOR_LENGTH(statcalcevent));
//	for (i = 0; i < VECTOR_LENGTH(statcalcevent); i++) {
//		ShowDebug("%s\n", VECTOR_INDEX(statcalcevent, i));
//		ShowDebug("%s\n", VECTOR_INDEX(statcalcevent, i)->script_buf);
//	}

	libconfig->destroy(&onpcstatcalcevent_conf);
	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", VECTOR_LENGTH(statcalcevent), confpath);
	return VECTOR_LENGTH(statcalcevent);
}

void status_calc_pc_additional_post(struct map_session_data *sd, enum e_status_calc_opt opt) {
	if (sd == NULL)
		return;
	for (int i = 0; i < VECTOR_LENGTH(statcalcevent); i++)
		script->run(VECTOR_INDEX(statcalcevent, i), 0, sd->bl.id, 0);
	return;
}

BUILDIN(recalculatestat) {
	struct map_session_data *sd;
	if (script_hasdata(st,2)) {
		if (data_isstring(script_getdata(st,2)))
			sd = map->nick2sd(script_getstr(st,2), true);
		else
			sd = map->id2sd(script_getnum(st,2));
	}
	else
		sd = script->rid2sd(st);
	if (sd)
		status_calc_pc(sd, SCO_FORCE);
	return true;
}

void clean_onpcstatcalcevent(void) {
	for (int i = 0; i < VECTOR_LENGTH(statcalcevent); ++i) {
		VECTOR_CLEAR(VECTOR_INDEX(statcalcevent, i)->script_buf);
		aFree(VECTOR_INDEX(statcalcevent, i));
	}
	VECTOR_CLEAR(statcalcevent);
	return;
}

int script_reload_post(int retVal) {
	clean_onpcstatcalcevent();
	read_onpcstatcalcevent();
	return retVal;
}

HPExport void plugin_init(void) {
	addHookPost(status, calc_pc_additional, status_calc_pc_additional_post);
	addScriptCommand("recalculatestat", "?", recalculatestat);
	addHookPost(script, reload, script_reload_post);
}

HPExport void server_online(void) {
	read_onpcstatcalcevent();
}

HPExport void plugin_final(void) {
	clean_onpcstatcalcevent();
}
 
Last edited by a moderator:
Back
Top