--- deliantra/server/plugins/cfperl/cfperl.xs 2006/05/09 17:48:28 1.52 +++ deliantra/server/plugins/cfperl/cfperl.xs 2006/08/14 07:10:47 1.68 @@ -47,11 +47,20 @@ #include +#include + +//#include "EventAPI.h" #include "perlxsi.c" +extern sint64 *levels; // the experience table + typedef object object_ornull; typedef mapstruct mapstruct_ornull; +typedef double val64; +#define newSVval64 newSVnv +#define SvVAL64 SvNV + static f_plug_api gethook; static f_plug_api registerGlobalEvent; static f_plug_api unregisterGlobalEvent; @@ -227,7 +236,7 @@ break; case CFAPI_LONG: - sv = newSVnv ((double)*va_arg (args, sint64 *)); /* oh, the humanity! */ + sv = newSVval64 ((val64)*va_arg (args, sint64 *)); break; case CFAPI_DOUBLE: @@ -251,38 +260,38 @@ switch (obj->type) { case MAP: - sv = newSVptr_cached (obj, "cf::object::map"); + sv = newSVptr_cached (obj, "cf::object::map::wrap"); break; case PLAYER: - sv = newSVptr_cached (obj, "cf::object::player"); + sv = newSVptr_cached (obj, "cf::object::player::wrap"); break; default: - sv = newSVptr_cached (obj, "cf::object"); + sv = newSVptr_cached (obj, "cf::object::wrap"); break; } } break; case CFAPI_PMAP: - sv = newSVptr (va_arg (args, mapstruct *), "cf::map"); + sv = newSVptr (va_arg (args, mapstruct *), "cf::map::wrap"); break; case CFAPI_PPLAYER: - sv = newSVptr (va_arg (args, player *), "cf::player"); + sv = newSVptr (va_arg (args, player *), "cf::player::wrap"); break; case CFAPI_PARCH: - sv = newSVptr (va_arg (args, archetype *), "cf::arch"); + sv = newSVptr (va_arg (args, archetype *), "cf::arch::wrap"); break; case CFAPI_PPARTY: - sv = newSVptr (va_arg (args, partylist *), "cf::party"); + sv = newSVptr (va_arg (args, partylist *), "cf::party::wrap"); break; case CFAPI_PREGION: - sv = newSVptr (va_arg (args, region *), "cf::region"); + sv = newSVptr (va_arg (args, region *), "cf::region::wrap"); break; default: @@ -296,8 +305,7 @@ ///////////////////////////////////////////////////////////////////////////// -int -initPlugin (const char *iversion, f_plug_api gethooksptr) +extern "C" int initPlugin (const char *iversion, f_plug_api gethooksptr) { gethook = gethooksptr; printf (PLUGIN_VERSION " init\n"); @@ -340,8 +348,7 @@ return returnvalue; } -void * -getPluginProperty (int *type, ...) +extern "C" void *getPluginProperty (int *type, ...) { va_list args; char *propname; @@ -374,12 +381,12 @@ else if (!strcmp (propname, "Identification")) { va_end (args); - return PLUGIN_NAME; + return (void*) PLUGIN_NAME; } else if (!strcmp (propname, "FullName")) { va_end (args); - return PLUGIN_VERSION; + return (void*) PLUGIN_VERSION; } else va_end (args); @@ -389,20 +396,19 @@ void *globalEventListener (int *type, ...); -int -postInitPlugin () +extern "C" int postInitPlugin () { int hooktype = 1; int rtype = 0; printf (PLUGIN_VERSION " post init\n"); - registerGlobalEvent = gethook (&rtype, hooktype, "cfapi_system_register_global_event"); - unregisterGlobalEvent = gethook (&rtype, hooktype, "cfapi_system_unregister_global_event"); - systemDirectory = gethook (&rtype, hooktype, "cfapi_system_directory"); - object_set_property = gethook (&rtype, hooktype, "cfapi_object_set_property"); - map_get_map = gethook (&rtype, hooktype, "cfapi_map_get_map"); - object_insert = gethook (&rtype, hooktype, "cfapi_object_insert"); + registerGlobalEvent = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_system_register_global_event"); + unregisterGlobalEvent = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_system_unregister_global_event"); + systemDirectory = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_system_directory"); + object_set_property = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_object_set_property"); + map_get_map = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_map_get_map"); + object_insert = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_object_insert"); cf_init_plugin (gethook); @@ -410,6 +416,10 @@ registerGlobalEvent (NULL, EVENT_BORN, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_CLOCK, PLUGIN_NAME, globalEventListener); //registerGlobalEvent (NULL, EVENT_CRASH, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_FIND_UNARMED_SKILL, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_PLAYER_USE_SKILL, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_CAST_SPELL, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_MONSTER_USE_SKILL, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_PLAYER_DEATH, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_GKILL, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_LOGIN, PLUGIN_NAME, globalEventListener); @@ -429,6 +439,7 @@ registerGlobalEvent (NULL, EVENT_FREE_OB, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_PLAYER_LOAD, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_PLAYER_SAVE, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_EXTCMD, PLUGIN_NAME, globalEventListener); char *argv[] = { "", @@ -444,6 +455,8 @@ perl = perl_alloc (); perl_construct (perl); + PL_exit_flags |= PERL_EXIT_DESTRUCT_END; + if (perl_parse (perl, xs_init, 2, argv, (char **)NULL) || perl_run (perl)) { printf ("unable to initialize perl-interpreter, continuing without.\n"); @@ -468,7 +481,7 @@ int event_code; if (!perl) - return; + return NULL; va_start (args, type); event_code = va_arg (args, int); @@ -487,6 +500,34 @@ rv = 0; } + else if (event_code == EVENT_CLOCK) + { + dSP; + int i, count; + + clean_obj_cache (); + + ENTER; + SAVETMPS; + + // service up to 8 events per tick better would be + // to check for elapsed time and stop processing after + // 0.25 * server_tick or so + for (i = 9; --i; ) + { + PUSHMARK (SP); + XPUSHs (sv_2mortal (newSViv (0))); + PUTBACK; + count = call_pv ("Event::one_event", G_SCALAR | G_EVAL); + SPAGAIN; + + if (!count || !POPi) + break; + } + + FREETMPS; + LEAVE; + } else { dSP; @@ -544,8 +585,27 @@ PUSH_PV; break; - case EVENT_CLOCK: - clean_obj_cache (); + case EVENT_FIND_UNARMED_SKILL: + PUSH_OB; + break; + + case EVENT_PLAYER_USE_SKILL: + case EVENT_MONSTER_USE_SKILL: + case EVENT_CAST_SPELL: + PUSH_OB; + PUSH_OB; + PUSH_OB; + PUSH_IV; + PUSH_PV; + break; + + case EVENT_EXTCMD: + PUSH_PL; + { + char *buf = va_arg (args, char *); + int len = va_arg (args, int); + PUSHs (sv_2mortal (newSVpvn (buf, len))); + } break; case EVENT_TELL: @@ -571,8 +631,7 @@ return &rv; } -void * -eventListener (int *type, ...) +extern "C" void * eventListener (int *type, ...) { static int rv; va_list args; @@ -581,7 +640,7 @@ char *message, *extension, *options; if (!perl) - return; + return NULL; va_start (args, type); who = va_arg (args, object *); @@ -617,15 +676,16 @@ case EVENT_TIMER: // $ob break; - case EVENT_APPLY: // $ob, $who - case EVENT_DROP: // $ob, $who - case EVENT_CLOSE: // $ob, $who - case EVENT_DEATH: // $ob[, $killer] - case EVENT_MOVE: // $ob, $enemy - case EVENT_THROW: // $ob, $thrower + case EVENT_APPLY: // $ob, $who + case EVENT_DROP: // $ob, $who + case EVENT_CLOSE: // $ob, $who + case EVENT_DEATH: // $ob[, $killer] + case EVENT_MOVE: // $ob, $enemy + case EVENT_THROW: // $ob, $thrower PUSHcfapi (POBJECT, activator); break; + case EVENT_DROP_ON: // $ob, $who, $what case EVENT_ATTACK: // $ob, $who, $victim (?? please god enlighten me) PUSHcfapi (POBJECT, activator); PUSHcfapi (POBJECT, third); @@ -664,8 +724,7 @@ return &rv; } -int -closePlugin () +extern "C" int closePlugin () { printf (PLUGIN_VERSION " closing\n"); @@ -1003,6 +1062,10 @@ const_iv (F_NOPICK) const_iv (F_LOCKED) + const_iv (F_BUY) + const_iv (F_SHOP) + const_iv (F_SELL) + const_iv (P_BLOCKSVIEW) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE) @@ -1119,6 +1182,47 @@ const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0) + + const_iv (PREFER_LOW) + const_iv (PREFER_HIGH) + + const_iv (ATNR_PHYSICAL) + const_iv (ATNR_MAGIC) + const_iv (ATNR_FIRE) + const_iv (ATNR_ELECTRICITY) + const_iv (ATNR_COLD) + const_iv (ATNR_CONFUSION) + const_iv (ATNR_ACID) + const_iv (ATNR_DRAIN) + const_iv (ATNR_WEAPONMAGIC) + const_iv (ATNR_GHOSTHIT) + const_iv (ATNR_POISON) + const_iv (ATNR_SLOW) + const_iv (ATNR_PARALYZE) + const_iv (ATNR_TURN_UNDEAD) + const_iv (ATNR_FEAR) + const_iv (ATNR_CANCELLATION) + const_iv (ATNR_DEPLETE) + const_iv (ATNR_DEATH) + const_iv (ATNR_CHAOS) + const_iv (ATNR_COUNTERSPELL) + const_iv (ATNR_GODPOWER) + const_iv (ATNR_HOLYWORD) + const_iv (ATNR_BLIND) + const_iv (ATNR_INTERNAL) + const_iv (ATNR_LIFE_STEALING) + const_iv (ATNR_DISEASE) + + const_iv (MAP_FLUSH) + const_iv (MAP_PLAYER_UNIQUE) + const_iv (MAP_BLOCK) + const_iv (MAP_STYLE) + const_iv (MAP_OVERLAY) + + const_iv (MAP_IN_MEMORY) + const_iv (MAP_SWAPPED) + const_iv (MAP_LOADING) + const_iv (MAP_SAVING) }; for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) @@ -1134,6 +1238,7 @@ const_event (ATTACK) const_event (DEATH) const_event (DROP) + const_event (DROP_ON) const_event (PICKUP) const_event (SAY) const_event (STOP) @@ -1145,7 +1250,7 @@ const_event (MOVE) const_event (BORN) - const_event (CLOCK) + //const_event (CLOCK) const_event (CRASH) const_event (PLAYER_DEATH) const_event (PLAYER_LOAD) @@ -1165,6 +1270,11 @@ const_event (TELL) const_event (MUZZLE) const_event (KICK) + const_event (PLAYER_USE_SKILL) + const_event (MONSTER_USE_SKILL) + const_event (CAST_SPELL) + const_event (FIND_UNARMED_SKILL) + const_event (EXTCMD) //const_event (FREE_OB) }; @@ -1308,18 +1418,35 @@ hv_store (prop_type, cprop->name, strlen (cprop->name), newSViv (cprop->dtype), 0); hv_store (prop_idx, cprop->name, strlen (cprop->name), newSViv (cprop->idx ), 0); } + + //I_EVENT_API (PACKAGE); } +NV floor (NV x) + +NV ceil (NV x) + void LOG (int level, char *msg) PROTOTYPE: $$ - C_ARGS: level, "%s", msg + C_ARGS: (LogLevel)level, "%s", msg + +char *path_combine (char *base, char *path) + PROTOTYPE: $$ + +char *path_combine_and_normalize (char *base, char *path) + PROTOTYPE: $$ char * cf_get_maps_directory (char *path) PROTOTYPE: $ ALIAS: maps_directory = 0 +void +sub_generation_inc () + CODE: + PL_sub_generation++; + char * mapdir () PROTOTYPE: @@ -1342,6 +1469,49 @@ cf_find_animation (char *text) PROTOTYPE: $ +int random_roll(int min, int max, object *op, int goodbad); + +const char *cost_string_from_value(uint64 cost, int approx = 0) + +int +exp_to_level (val64 exp) + CODE: +{ + int i = 0; + + RETVAL = settings.max_level; + + for (i = 1; i <= settings.max_level; i++) + { + if (levels[i] > exp) + { + RETVAL = i - 1; + break; + } + } +} + OUTPUT: RETVAL + +val64 +level_to_min_exp (int level) + CODE: + if (level > settings.max_level) + RETVAL = levels[settings.max_level]; + else if (level < 1) + RETVAL = 0; + else + RETVAL = levels[level]; + OUTPUT: RETVAL + +SV * +resistance_to_string (int atnr) + CODE: + if (atnr >= 0 && atnr < NROFATTACKS) + RETVAL = newSVpv (resist_plus[atnr], 0); + else + XSRETURN_UNDEF; + OUTPUT: RETVAL + MODULE = cf PACKAGE = cf::object PREFIX = cf_object_ SV * @@ -1359,7 +1529,7 @@ cf_object_set_int_property (obj, idx, SvIV (newval)); break; case CFAPI_LONG: - cf_object_set_long_property (obj, idx, SvNV (newval)); + cf_object_set_long_property (obj, idx, (long) SvVAL64 (newval)); break; case CFAPI_DOUBLE: { @@ -1447,7 +1617,11 @@ int cf_object_pay_item (object *op, object *buyer) -int cf_object_pay_amount (object *op, double amount) +int cf_object_pay_amount (object *op, uint64 amount) + +void pay_player (object *op, uint64 amount) + +val64 pay_player_arch (object *op, const char *arch, uint64 amount) int cf_object_cast_spell (object *caster, object *ctoo, int dir, object *spell_ob, char *stringarg = 0) @@ -1494,12 +1668,29 @@ object *cf_create_object_by_name (const char *name) -void change_exp (object *op, double exp, const char *skill_name = 0, int flag = 0) +void change_exp (object *op, uint64 exp, const char *skill_name = 0, int flag = 0) void player_lvl_adj (object *who, object *skill = 0) int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL) +int calc_skill_exp (object *who, object *op, object *skill); + +void push_button (object *op); + +void use_trigger (object *op); + +void add_button_link (object *button, mapstruct *map, int connected); + +void remove_button_link (object *op); + +void +cf_object_set_resistance (object *op, int rtype, int val) + CODE: + if (rtype >= 0 && rtype < NROFATTACKS) + op->resist[rtype] = val; + + MODULE = cf PACKAGE = cf::object PREFIX = cf_ void cf_fix_object (object *pl) @@ -1532,6 +1723,11 @@ OUTPUT: RETVAL +player *contr (object *op) + CODE: + RETVAL = op->contr; + OUTPUT: RETVAL + const char *get_ob_key_value (object *op, const char *key) bool set_ob_key_value (object *op, const char *key, const char *value = 0, int add_key = 1) @@ -1584,11 +1780,6 @@ object *cf_player_send_inventory (object *op) -player *contr (object *op) - CODE: - RETVAL = op->contr; - OUTPUT: RETVAL - char *cf_player_get_ip (object *op) ALIAS: ip = 0 @@ -1602,8 +1793,6 @@ void cf_player_set_party (object *op, partylist *party) -void change_skill (object *op, double exp, char *skill_name = 0, int flag = 0) - void kill_player (object *op) MODULE = cf PACKAGE = cf::object::map PREFIX = cf_ @@ -1635,6 +1824,24 @@ RETVAL = pl->next; OUTPUT: RETVAL +bool +cell_visible (player *pl, int dx, int dy) + CODE: + RETVAL = FABS (dx) <= pl->socket.mapx / 2 && FABS (dy) <= pl->socket.mapy / 2 + && !pl->blocked_los [dx + pl->socket.mapx / 2][dy + pl->socket.mapy / 2]; + OUTPUT: + RETVAL + +void +send (player *pl, SV *packet) + CODE: +{ + STRLEN len; + char *buf = SvPVbyte (packet, len); + + Write_String_To_Socket (&pl->socket, buf, len); +} + int listening (player *pl, int new_value = -1) CODE: @@ -1716,7 +1923,7 @@ CODE: { int unused_type; - RETVAL = map_get_map (&unused_type, 0, width, height); + RETVAL = (mapstruct*) map_get_map (&unused_type, 0, width, height); } OUTPUT: RETVAL @@ -1727,21 +1934,44 @@ void play_sound_map (mapstruct *map, int x, int y, int sound_num) +mapstruct *tile_map (mapstruct *map, unsigned int dir) + CODE: + RETVAL = dir < 4 ? map->tile_map [dir] : 0; + OUTPUT: + RETVAL + +char *tile_path (mapstruct *map, unsigned int dir) + CODE: + if (dir >= 4) + XSRETURN_UNDEF; + RETVAL = map->tile_path [dir]; + OUTPUT: + RETVAL + mapstruct *cf_map_get_map (char *name) PROTOTYPE: $ ALIAS: map = 0 +mapstruct *has_been_loaded (char *name) + PROTOTYPE: $ + mapstruct *cf_map_get_first () PROTOTYPE: ALIAS: first = 0 # whoever "designed" the plug-in api should have wasted -# his/her time with staying away form the project - would have +# his/her time with staying away from the project - would have # saved others a lot of time, without doubt. void set_path (mapstruct *where, char *path) CODE: strcpy (where->path, path); +int in_memory (mapstruct *map) + CODE: + RETVAL = map->in_memory; + OUTPUT: + RETVAL + bool unique (mapstruct *map) CODE: RETVAL = map->unique; @@ -1759,19 +1989,39 @@ object* cf_map_present_arch_by_name (mapstruct *map, const char* str, int nx, int ny) C_ARGS: str, map, nx, ny -#int cf_map_get_flags (mapstruct* map, mapstruct** nmap, I16 x, I16 y, I16 *nx, I16 *ny) +void +cf_map_normalise (mapstruct *map, int x, int y) + PPCODE: +{ + mapstruct *nmap = 0; + I16 nx = 0, ny = 0; + int flags = cf_map_get_flags (map, &nmap, x, y, &nx, &ny); + + EXTEND (SP, 4); + PUSHs (sv_2mortal (newSViv (flags))); + + if (GIMME_V == G_ARRAY) + { + PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap))); + PUSHs (sv_2mortal (newSViv (nx))); + PUSHs (sv_2mortal (newSViv (ny))); + } +} void -at (mapstruct *obj, unsigned int x, unsigned int y) +at (mapstruct *map, unsigned int x, unsigned int y) PROTOTYPE: $$$ - INIT: - if (x >= MAP_WIDTH (obj) || y >= MAP_HEIGHT (obj)) XSRETURN_EMPTY; PPCODE: { object *o; - - for (o = GET_MAP_OB (obj, x, y); o; o = o->above) - XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o))); + mapstruct *nmap = 0; + I16 nx, ny; + + cf_map_get_flags (map, &nmap, x, y, &nx, &ny); + + if (nmap) + for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above) + XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o))); } SV * @@ -1893,6 +2143,9 @@ const char *cf_archetype_get_name (archetype *arch) ALIAS: name = 0 +object *cf_archetype_get_clone (archetype *arch) + ALIAS: clone = 0 + MODULE = cf PACKAGE = cf::party PREFIX = cf_party_ partylist *cf_party_get_first () @@ -1938,8 +2191,8 @@ MODULE = cf PACKAGE = cf::living PREFIX = cf_living_ -double -exp (living *liv, double new_val = 0.) +val64 +exp (living *liv, val64 new_val = 0) PROTOTYPE: $;$ ALIAS: Str = 1 @@ -1961,7 +2214,7 @@ dam = 17 luck = 18 CODE: -# define LIVING_ACC(acc,idx) case idx: RETVAL = liv->acc; if (items > 1) liv->acc = new_val; break +# define LIVING_ACC(acc,idx) case idx: RETVAL = liv->acc; if (items > 1) liv->acc = (sint64)new_val; break switch (ix) { LIVING_ACC (exp , 0);