* Patches to allow everything to work right. + 1 more sample script.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@6779 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
Lance 2006-05-26 18:54:07 +00:00
parent 2e8e53738f
commit 2681e4127b
11 changed files with 235 additions and 65 deletions

View File

@ -4,6 +4,7 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/05/26
* Patches to allow everything to work right. + 1 more sample script. [Lance]
* Mob control engine tested 99% working so far. [Lance]
* Change scripting engine's NPC scope vars to dot (.) style.
* Improved and (should be fully) fixed the mob control engine. [Lance]

View File

@ -710,6 +710,8 @@ AI_ACTION_TYPE_ATTACK 1
AI_ACTION_TYPE_DETECT 2
AI_ACTION_TYPE_DEAD 3
AI_ACTION_TYPE_ASSIST 4
AI_ACTION_TYPE_KILL 5
AI_ACTION_TYPE_UNLOCK 6
ALL_CLIENT 0
ALL_SAMEMAP 1

View File

@ -28,6 +28,8 @@
1902,14,1,6,6,1101,2105,0,0,0,32,3
// Poki#3
1903,4012,1,21,0,1720,0,102,184,57,16,0
// Sentry
1904,1286,0
// eAthena Custom Equipped Mobs
1970,1002,10013

View File

@ -19,6 +19,7 @@
1901,VALARIS_WORSHIPPER,Valaris's Worshipper,Valaris's Worshipper,50,8578,0,2706,1480,1,487,590,15,25,1,75,55,1,93,45,10,12,0,6,27,1685,100,868,480,120,0,0,0,0,0,0,0,0,923,500,984,63,1464,2,607,50,610,100,503,300,2405,50,0,0,0,0,4129,1
1902,MC_CAMERI,MC Cameri,MC Cameri,99,668000,0,107250,37895,2,3220,4040,35,45,1,152,96,85,120,95,10,10,2,6,67,1973,100,1068,768,576,13000,5000,608,1000,750,400,923,3800,1466,200,2256,200,2607,800,714,500,617,3000,984,4300,985,5600,0,0,0,0,4147,1
1903,POKI,Poki#3,Poki#3,99,1349000,0,4093000,1526000,9,4892,9113,22,35,1,180,39,67,193,130,10,12,1,7,64,1973,120,500,672,480,92100,7000,603,5500,617,3000,1723,1000,1228,100,1236,500,617,2500,1234,75,1237,125,1722,250,1724,100,1720,50,0,0,0,0
1904,SENTRY,Sentry,Sentry,99,668000,0,107250,37895,2,3220,4040,35,45,1,152,96,85,120,95,10,10,2,6,67,1973,100,1068,768,576,13000,5000,608,1000,750,400,923,3800,1466,200,2256,200,2607,800,714,500,617,3000,984,4300,985,5600,0,0,0,0,4147,1
// Mobs used for eAthena's Custom Equipped Mobs
1970,PORING_,Pet Poring,Pet Poring,1,50,0,2,1,1,7,10,0,5,1,1,1,1,6,30,10,12,1,3,21,131,400,1872,672,480,0,0,0,0,0,0,0,0,909,7000,1202,100,938,400,512,1000,713,1500,741,5,619,20,0,0,0,0,4001,20

119
npc/custom/Lance/Sentry.cpp Normal file
View File

@ -0,0 +1,119 @@
//(=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)
//( (c)2006 eAthena Development Team presents )
//( ______ __ __ )
//( /\ _ \/\ \__/\ \ v 1.00.00 )
//( __\ \ \_\ \ \ ,_\ \ \___ __ ___ __ )
//( /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\ )
//( /\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \_\.\_ )
//( \ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\ )
//( \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/ )
//( _ _ _ _ _ _ _ _ _ _ _ _ _ )
//( / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ )
//( ( e | A | t | h | e | n | a ) ( S | c | r | i | p | t ) )
//( \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ )
//( )
//(=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)
// Programmed by [Lance] ver. 1.0
// ---------------------------------------------------------
// [ Sentry System ]
// - Guards main towns against aggresive monsters and bad
// players.
// [ Customization ]
// - See OnInit:
// =========================================================
- script sentry_system -1,{
function spawn_guardian {
set .mob_id[getarg(0)], spawnmob("Guardian Sentry",1904,.mob_map$[getarg(0)],.mob_x[getarg(0)],.mob_y[getarg(0)]);
mobattach .mob_id[getarg(0)]; // Attach events to this script.
mobrandomwalk .mob_id[getarg(0)], 0; // Prevents random walking.
mobattack .mob_id[getarg(0)]; // Enable all viewing.
return;
}
function search_entry {
set .@tmp, getarraysize(getarg(0));
for(set .@i, 0; .@i < .@tmp; set .@i, .@i + 1){
if(getelementofarray(getarg(0),.@i) == getarg(1))
break;
}
if(.@i == .@tmp)
return -1;
else
return .@i;
}
// Script Entry Point - When an event from the script engine is received.
if(getarraysize(.ai_action) == 4){ // Checks if the data is formatted correctly.
set .@tmp, search_entry(.mob_id, .ai_action[AI_ACTION_SRC]);
switch(.ai_action[AI_ACTION_TYPE]){
case AI_ACTION_TYPE_DETECT: // We see something...
if(.ai_busy[.@tmp] == 0){ // Not busy
switch(.ai_action[AI_ACTION_TAR_TYPE]){ // Check what have we here.
case AI_ACTION_TAR_TYPE_PC: // It's a player
if(getd("$pkarma_"+.ai_action[AI_ACTION_TAR]) > .karma){ // pkarma is higher?
mobtalk .ai_action[AI_ACTION_SRC], "Who goes there!";
mobemote .ai_action[AI_ACTION_SRC], e_gasp; // !
mobattack .ai_action[AI_ACTION_SRC],.ai_action[AI_ACTION_TAR];
// We're currently busy.
set .ai_busy[.@tmp], .ai_action[AI_ACTION_TAR];
}
break;
case AI_ACTION_TAR_TYPE_MOB: // It's a monster
if(.ai_action[AI_ACTION_TAR] != .ai_action[AI_ACTION_SRC]){
getmobdata .ai_action[AI_ACTION_TAR], .@temp;
if(.@temp[9]&0x804){ // In Aggressive mode?
mobtalk .ai_action[AI_ACTION_SRC], "Protect the villagers we must!";
mobemote .ai_action[AI_ACTION_SRC], e_gasp; // !
mobattack .ai_action[AI_ACTION_SRC],.ai_action[AI_ACTION_TAR];
// We're currently busy.
set .ai_busy[.@tmp], .ai_action[AI_ACTION_TAR];
}
}
break;
}
}
break;
case AI_ACTION_TYPE_KILL: // We eliminated the criminal
if(.ai_action[AI_ACTION_TAR_TYPE] == AI_ACTION_TAR_TYPE_PC)
setd "$pkarma_"+.ai_action[AI_ACTION_TAR], 0;
case AI_ACTION_TYPE_UNLOCK: // Target lost :(
if(.@tmp != -1){
set .ai_busy[.@tmp], 0; // Remove him, we're free.
}
// Walk back to where we came from.
mobwalk .ai_action[AI_ACTION_SRC],.mob_x[.@tmp],.mob_y[.@tmp];
break;
case AI_ACTION_TYPE_DEAD: // We got killed :(
if(.ai_action[AI_ACTION_TAR_TYPE] == AI_ACTION_TAR_TYPE_PC){ // Attacker is a player?
setd "$pkarma_"+.ai_action[AI_ACTION_TAR], getd("$pkarma_"+.ai_action[AI_ACTION_TAR]) + 5;
}
sleep 10000; // 10 seconds until reinforcements arrive
spawn_guardian .@tmp;
break;
case AI_ACTION_TYPE_ATTACK: // Someone attacked us
if(.ai_action[AI_ACTION_TAR_TYPE] == AI_ACTION_TAR_TYPE_PC){ // Attacker is a player?
setd "$pkarma_"+.ai_action[AI_ACTION_TAR], getd("$pkarma_"+.ai_action[AI_ACTION_TAR]) + 1;
}
// The system's AI will auto attack any attackers. So we leave it here.
break;
}
}
deletearray .ai_action, getarraysize(.ai_action); // Cleans up and frees up memory
end;
OnInit:
// Customization ---------------------------------------------------------------------
setarray .mob_map$, "prt_fild08.gat", "prt_fild05.gat", "prt_fild06.gat", "prt_gld.gat";
setarray .mob_x,176,369,29,165;
setarray .mob_y,372,201,187,37;
set .karma, 5;
// -----------------------------------------------------------------------------------
set .@tmp, getarraysize(.mob_map$);
for(set .@i, 0; .@i < .@tmp; set .@i, .@i + 1){
spawn_guardian .@i;
}
debugmes "[Sentry System] Spawned " + .@i + " guardians.";
end;
}

View File

@ -69,14 +69,26 @@ prontera.gat,180,200,4 script Monster Controller 123,{
break;
}
if(.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_ATTACK)
set .@action_type$, "Attacked by";
else if(.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_DETECT)
set .@action_type$, "Detected";
else if (.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_ASSIST)
set .@action_type$, "Killed by";
else
set .@action_type$, "Assisting";
switch(.ai_action[AI_ACTION_TYPE]){
case AI_ACTION_TYPE_ATTACK:
set .@action_type$, "Attacked by";
break;
case AI_ACTION_TYPE_DETECT:
set .@action_type$, "Detected";
break;
case AI_ACTION_TYPE_DEAD:
set .@action_type$, "Killed by";
break;
case AI_ACTION_TYPE_ASSIST:
set .@action_type$, "Assisting";
break;
case AI_ACTION_TYPE_UNLOCK:
set .@action_type$, "Unlocked target";
break;
case AI_ACTION_TYPE_KILL:
set .@action_type$, "Killed";
break;
}
announce "Details - " + .@action_type$ + " [" + .@action_from$ + "] " + .@action_name$ + "!", bc_all;
deletearray .ai_action, 4;

View File

@ -20,7 +20,6 @@
//npc: npc/location/to/script.txt
// Your scripts go here!!
// --------------------------------------------------------------
//npc: npc/sample/monster_controller.cpp
// ----------------------- Basic Scripts -----------------------
// -- Adoption NPC [Fredzilla]
npc: npc/custom/adoption.txt
@ -91,6 +90,8 @@ npc: npc/custom/adoption.txt
//npc: npc/custom/Lance/FR_WeatherController.c
//npc: npc/custom/Lance/FR_MailSystem.c
//npc: npc/sample/npc_dynamic_shop.txt
//npc: npc/sample/monster_controller.cpp
//npc: npc/custom/Lance/Sentry.cpp
// --------------------------------------------------------------
// --------------------------------------------------------------

View File

@ -808,7 +808,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
setd_sub(NULL, NULL, ".ai_action", 2, (void *)bl->id, &md->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 3, (void *)md->bl.id, &md->nd->u.scr.script->script_vars);
run_script(md->nd->u.scr.script, 0, 0, md->nd->bl.id);
return 0; // We have script handling the work.
return 1; // We have script handling the work.
}
if(battle_check_target(&md->bl,bl,BCT_ENEMY)<=0)
@ -997,6 +997,15 @@ int mob_unlocktarget(struct mob_data *md,int tick)
{
nullpo_retr(0, md);
if(md->nd){
struct block_list *tbl = map_id2bl(md->target_id);
setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)6, &md->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)(tbl?tbl->type:0), &md->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 2, (void *)(tbl?tbl->id:0), &md->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 3, (void *)md->bl.id, &md->nd->u.scr.script->script_vars);
run_script(md->nd->u.scr.script, 0, 0, md->nd->bl.id);
}
md->target_id=0;
md->state.skillstate=MSS_IDLE;
md->next_walktime=tick+rand()%3000+3000;
@ -2160,6 +2169,17 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
guild_agit_break(md);
}
if(src->type == BL_MOB){
struct mob_data *smd = (struct mob_data *)src;
if(smd->nd){
setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)5, &smd->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)md->bl.type, &smd->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 2, (void *)md->bl.id, &smd->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 3, (void *)smd->bl.id, &smd->nd->u.scr.script->script_vars);
run_script(smd->nd->u.scr.script, 0, 0, smd->nd->bl.id);
}
}
if(md->nd){
setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)3, &md->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)src->type, &md->nd->u.scr.script->script_vars);

View File

@ -4527,37 +4527,48 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
}
clif_clearchar_area(&sd->bl,1);
if (src && src->type == BL_PC) {
struct map_session_data *ssd = (struct map_session_data *)src;
if (ssd) {
if (sd->state.event_death)
pc_setglobalreg(sd,"killerrid",(ssd->status.account_id));
if (ssd->state.event_kill_pc) {
pc_setglobalreg(ssd, "killedrid", sd->bl.id);
npc_script_event(ssd, NPCE_KILLPC);
if (src) {
if(src->type == BL_MOB){
struct mob_data *smd = (struct mob_data *)src;
if(smd->nd){
setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)5, &smd->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)sd->bl.type, &smd->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 2, (void *)sd->bl.id, &smd->nd->u.scr.script->script_vars);
setd_sub(NULL, NULL, ".ai_action", 3, (void *)smd->bl.id, &smd->nd->u.scr.script->script_vars);
run_script(smd->nd->u.scr.script, 0, 0, smd->nd->bl.id);
}
if (battle_config.pk_mode && ssd->status.manner >= 0 && battle_config.manner_system) {
ssd->status.manner -= 5;
if(ssd->status.manner < 0)
sc_start(src,SC_NOCHAT,100,0,0);
// PK/Karma system code (not enabled yet) [celest]
// originally from Kade Online, so i don't know if any of these is correct ^^;
// note: karma is measured REVERSE, so more karma = more 'evil' / less honourable,
// karma going down = more 'good' / more honourable.
// The Karma System way...
/*if (sd->status.karma > ssd->status.karma) { // If player killed was more evil
sd->status.karma--;
ssd->status.karma--;
} else if(src->type == BL_PC){
struct map_session_data *ssd = (struct map_session_data *)src;
if (ssd) {
if (sd->state.event_death)
pc_setglobalreg(sd,"killerrid",(ssd->status.account_id));
if (ssd->state.event_kill_pc) {
pc_setglobalreg(ssd, "killedrid", sd->bl.id);
npc_script_event(ssd, NPCE_KILLPC);
}
else if (sd->status.karma < ssd->status.karma) // If player killed was more good
ssd->status.karma++;*/
if (battle_config.pk_mode && ssd->status.manner >= 0 && battle_config.manner_system) {
ssd->status.manner -= 5;
if(ssd->status.manner < 0)
sc_start(src,SC_NOCHAT,100,0,0);
// or the PK System way...
/* if (sd->status.karma > 0) // player killed is dishonourable?
ssd->status.karma--; // honour points earned
sd->status.karma++; // honour points lost */
// To-do: Receive exp on certain occasions
// PK/Karma system code (not enabled yet) [celest]
// originally from Kade Online, so i don't know if any of these is correct ^^;
// note: karma is measured REVERSE, so more karma = more 'evil' / less honourable,
// karma going down = more 'good' / more honourable.
// The Karma System way...
/*if (sd->status.karma > ssd->status.karma) { // If player killed was more evil
sd->status.karma--;
ssd->status.karma--;
}
else if (sd->status.karma < ssd->status.karma) // If player killed was more good
ssd->status.karma++;*/
// or the PK System way...
/* if (sd->status.karma > 0) // player killed is dishonourable?
ssd->status.karma--; // honour points earned
sd->status.karma++; // honour points lost */
// To-do: Receive exp on certain occasions
}
}
}
} else {

View File

@ -10514,37 +10514,38 @@ int buildin_getmobdata(struct script_state *st) {
int num, id;
char *name;
struct mob_data *md = NULL;
struct map_session_data *sd = st->rid?map_id2sd(st->rid):NULL;
id = conv_num(st, & (st->stack->stack_data[st->start+2]));
if(!(md = (struct mob_data *)map_id2bl(id)) || st->stack->stack_data[st->start+3].type!=C_NAME ){
ShowWarning("buildin_getmobdata: Error in argument!\n");
} else {
num=st->stack->stack_data[st->start+3].u.num;
name=(char *)(str_buf+str_data[num&0x00ffffff].str);
setd_sub(st,map_id2sd(st->rid),name,0,(void *)(int)md->class_,NULL);
setd_sub(st,map_id2sd(st->rid),name,1,(void *)(int)md->level,NULL);
setd_sub(st,map_id2sd(st->rid),name,2,(void *)(int)md->hp,NULL);
setd_sub(st,map_id2sd(st->rid),name,3,(void *)(int)md->max_hp,NULL);
setd_sub(st,map_id2sd(st->rid),name,4,(void *)(int)md->master_id,NULL);
setd_sub(st,map_id2sd(st->rid),name,5,(void *)(int)md->bl.m,NULL);
setd_sub(st,map_id2sd(st->rid),name,6,(void *)(int)md->bl.x,NULL);
setd_sub(st,map_id2sd(st->rid),name,7,(void *)(int)md->bl.y,NULL);
setd_sub(st,map_id2sd(st->rid),name,8,(void *)(int)md->speed,NULL);
setd_sub(st,map_id2sd(st->rid),name,9,(void *)(int)md->mode,NULL);
setd_sub(st,map_id2sd(st->rid),name,10,(void *)(int)md->special_state.ai,NULL);
setd_sub(st,map_id2sd(st->rid),name,11,(void *)(int)md->db->option,NULL);
setd_sub(st,map_id2sd(st->rid),name,12,(void *)(int)md->vd->sex,NULL);
setd_sub(st,map_id2sd(st->rid),name,13,(void *)(int)md->vd->class_,NULL);
setd_sub(st,map_id2sd(st->rid),name,14,(void *)(int)md->vd->hair_style,NULL);
setd_sub(st,map_id2sd(st->rid),name,15,(void *)(int)md->vd->hair_color,NULL);
setd_sub(st,map_id2sd(st->rid),name,16,(void *)(int)md->vd->head_bottom,NULL);
setd_sub(st,map_id2sd(st->rid),name,17,(void *)(int)md->vd->head_mid,NULL);
setd_sub(st,map_id2sd(st->rid),name,18,(void *)(int)md->vd->head_top,NULL);
setd_sub(st,map_id2sd(st->rid),name,19,(void *)(int)md->vd->cloth_color,NULL);
setd_sub(st,map_id2sd(st->rid),name,20,(void *)(int)md->vd->shield,NULL);
setd_sub(st,map_id2sd(st->rid),name,21,(void *)(int)md->vd->weapon,NULL);
setd_sub(st,map_id2sd(st->rid),name,22,(void *)(int)md->vd->shield,NULL);
setd_sub(st,map_id2sd(st->rid),name,23,(void *)(int)md->ud.dir,NULL);
setd_sub(st,map_id2sd(st->rid),name,24,(void *)(int)md->state.killer,NULL);
setd_sub(st,sd,name,0,(void *)(int)md->class_,NULL);
setd_sub(st,sd,name,1,(void *)(int)md->level,NULL);
setd_sub(st,sd,name,2,(void *)(int)md->hp,NULL);
setd_sub(st,sd,name,3,(void *)(int)md->max_hp,NULL);
setd_sub(st,sd,name,4,(void *)(int)md->master_id,NULL);
setd_sub(st,sd,name,5,(void *)(int)md->bl.m,NULL);
setd_sub(st,sd,name,6,(void *)(int)md->bl.x,NULL);
setd_sub(st,sd,name,7,(void *)(int)md->bl.y,NULL);
setd_sub(st,sd,name,8,(void *)(int)md->speed,NULL);
setd_sub(st,sd,name,9,(void *)(int)(md->mode?md->mode:md->db->mode),NULL);
setd_sub(st,sd,name,10,(void *)(int)md->special_state.ai,NULL);
setd_sub(st,sd,name,11,(void *)(int)md->db->option,NULL);
setd_sub(st,sd,name,12,(void *)(int)md->vd->sex,NULL);
setd_sub(st,sd,name,13,(void *)(int)md->vd->class_,NULL);
setd_sub(st,sd,name,14,(void *)(int)md->vd->hair_style,NULL);
setd_sub(st,sd,name,15,(void *)(int)md->vd->hair_color,NULL);
setd_sub(st,sd,name,16,(void *)(int)md->vd->head_bottom,NULL);
setd_sub(st,sd,name,17,(void *)(int)md->vd->head_mid,NULL);
setd_sub(st,sd,name,18,(void *)(int)md->vd->head_top,NULL);
setd_sub(st,sd,name,19,(void *)(int)md->vd->cloth_color,NULL);
setd_sub(st,sd,name,20,(void *)(int)md->vd->shield,NULL);
setd_sub(st,sd,name,21,(void *)(int)md->vd->weapon,NULL);
setd_sub(st,sd,name,22,(void *)(int)md->vd->shield,NULL);
setd_sub(st,sd,name,23,(void *)(int)md->ud.dir,NULL);
setd_sub(st,sd,name,24,(void *)(int)md->state.killer,NULL);
}
return 0;
}

View File

@ -1084,8 +1084,8 @@ int unit_attack(struct block_list *src,int target_id,int type)
return 0;
}
if(battle_check_target(src,target,BCT_ENEMY)<=0 ||
!status_check_skilluse(src, target, 0, 0)
if(!(src->type == BL_MOB && !((TBL_MOB *)src)->state.killer) && (battle_check_target(src,target,BCT_ENEMY)<=0 ||
!status_check_skilluse(src, target, 0, 0))
) {
unit_unattackable(src);
return 1;