#include <rtlimits.h>#include <debug_info.h>#include <thing/properties.h>#include <player/base.h>#include <moving.h>#include <config.h>#include <wizlevels.h>#include <defines.h>#include <language.h>#include <hook.h>#include <player/pklog.h>#include <player/combat.h>#include <health.h>#include <living/combat.h>#include <attributes.h>#include <defuel.h>#include <new_skills.h>
gehe zum Quellcode dieser Datei
Makrodefinitionen | |
| #define | NEED_PROTOTYPES |
| #define | SUFFER_TIME 7200 |
| #define | P_DEATH_INFO "death_info" |
Funktionen | |
| static int | _set_playerkills (int val) |
| protected void | create () |
| protected void | reconnect () |
| public int | death_suffering () |
| protected void | heart_beat () |
| public void | force_save () |
| nomask public int | do_damage (int dam, object enemy) |
| private void | reset_my_properties () |
| varargs protected int | second_life (object corpse) |
| public int | AddHpHook (object ob) |
| public int | RemoveHpHook (object ob) |
| static int | _set_hp (int hp) |
| static int | _set_sp (int sp) |
| static int | _set_ghost (int g) |
| public int | undie () |
| varargs public void | die (int poisondeath, int extern) |
| int | defuel_food () |
| int | defuel_drink () |
Variablen | |
| inherit std living | life |
| private int | suffer_time |
| static int | time_to_save |
| private nosave int | die_in_progress |
| #define P_DEATH_INFO "death_info" |
| static int _set_ghost | ( | int | g | ) | [static] |
Definiert in Zeile 515 der Datei life.c.
00515 { 00516 object team; 00517 00518 if(!g && query_hc_play()>1) 00519 { 00520 write("HAHAHA, DU BIST AUF EWIG MEIN.\n"); 00521 return Query(P_GHOST); 00522 } 00523 00524 g = Set( P_GHOST, g ); 00525 00526 if ( g && objectp(team = Query(P_TEAM)) ) 00527 team->RemoveMember(ME); 00528 00529 return g; 00530 }
| static int _set_hp | ( | int | hp | ) | [static] |
Definiert in Zeile 468 der Datei life.c.
00469 { 00470 object *hooks; 00471 int ret, i, old; 00472 00473 if ( (old = Query(P_HP)) == hp ) 00474 return old; 00475 00476 ret = life::_set_hp(hp); 00477 00478 if ( ret == old ) 00479 return hp; 00480 00481 // Call old hooks in all objects... destructed objects will be ignored. 00482 if (pointerp(hooks = Query(P_HP_HOOKS))) 00483 call_other(hooks, "NotifyHpChange"); 00484 00485 // Call new hooks. 00486 HookFlow(H_HOOK_HP,ret); 00487 00488 return ret; 00489 }
| static int _set_playerkills | ( | int | val | ) | [static] |
Definiert in Zeile 78 der Datei life.c.
00079 { 00080 string tmp; 00081 int playerkills; 00082 00083 // ist der Setzer in einer Arena/Schattenwelt. Dann nicht. (Ja, Bug ist, 00084 // dass EMs aus Schattenwelt/Arena heraus auch das PK-Flag nicht 00085 // zuruecksetzen koennen.) 00086 if ( previous_object(1) && environment(previous_object(1)) && 00087 (tmp = object_name(environment(previous_object(1)))) && 00088 CheckArenaFight(previous_object(1)) ) 00089 return 0; 00090 00091 tmp = sprintf( "%O: %s %O %s", 00092 previous_object(1) || this_interactive() || this_player(), 00093 getuid(ME), val, dtime(time()) ); 00094 00095 playerkills = Query(P_KILLS); 00096 00097 if( intp(val) && val >= 0 ) 00098 if( previous_object(1) && IS_ARCH(getuid(previous_object(1))) && 00099 this_interactive() && IS_ARCH(this_interactive()) ) 00100 playerkills = val; 00101 else 00102 tmp += " ILLEGAL!"; 00103 else 00104 playerkills++; 00105 00106 if ( !previous_object(1) || !query_once_interactive(previous_object(1)) || 00107 IS_LEARNER(previous_object(1)) ) 00108 log_file( "SET_KILLS", tmp + "\n" ); 00109 00110 return Set( P_KILLS, playerkills ); 00111 }
| static int _set_sp | ( | int | sp | ) | [static] |
Definiert in Zeile 492 der Datei life.c.
00493 { 00494 object *hooks; 00495 int ret, i, old; 00496 00497 if ( (old = Query(P_SP)) == sp ) 00498 return old; 00499 00500 ret = life::_set_sp(sp); 00501 00502 if ( ret == old ) 00503 return sp; 00504 00505 // Call old hooks in all objects... destructed objects will be ignored. 00506 if (pointerp(hooks = Query(P_HP_HOOKS))) 00507 call_other(hooks, "NotifyHpChange"); 00508 00509 // Call new hooks. 00510 HookFlow(H_HOOK_SP,ret); 00511 00512 return ret; 00513 }
| public int AddHpHook | ( | object | ob | ) |
Definiert in Zeile 436 der Datei life.c.
00437 { 00438 object *hooks; 00439 00440 if ( !objectp(ob) ) 00441 return 0; 00442 00443 if ( !pointerp(hooks = Query(P_HP_HOOKS)) ){ 00444 Set( P_HP_HOOKS, ({ ob }) ); 00445 return 1; 00446 } 00447 00448 if ( member( hooks, ob ) >= 0 ) 00449 return 0; 00450 00451 Set( P_HP_HOOKS, (hooks - ({0})) + ({ ob }) ); 00452 return 1; 00453 }
| protected void create | ( | ) |
Definiert in Zeile 52 der Datei life.c.
Benutzt call_out(), create(), F_MODE_AS, H_HOOK_HP, H_HOOK_SP, offerHook(), P_DEATH_INFO, P_DEFUEL_AMOUNT_DRINK, P_DEFUEL_AMOUNT_FOOD, P_DEFUEL_LIMIT_DRINK, P_DEFUEL_LIMIT_FOOD, P_DEFUEL_TIME_DRINK, P_DEFUEL_TIME_FOOD, P_GHOST, P_KILLS, P_LAST_DEATH_TIME, P_TIMING_MAP, PROTECTED, SAVE, SECURED und Set().
00053 { 00054 ::create(); 00055 Set( P_KILLS, SAVE|SECURED, F_MODE_AS ); 00056 Set( P_GHOST, SAVE, F_MODE_AS ); 00057 Set( P_TIMING_MAP, SAVE|SECURED, F_MODE_AS ); 00058 Set( P_LAST_DEATH_TIME, SAVE|SECURED, F_MODE_AS ); 00059 Set( P_DEATH_INFO, SAVE|SECURED, F_MODE_AS ); 00060 Set( P_DEFUEL_LIMIT_FOOD,PROTECTED,F_MODE_AS); 00061 Set( P_DEFUEL_LIMIT_DRINK,PROTECTED,F_MODE_AS); 00062 Set( P_DEFUEL_TIME_FOOD,PROTECTED,F_MODE_AS); 00063 Set( P_DEFUEL_TIME_DRINK,PROTECTED,F_MODE_AS); 00064 Set( P_DEFUEL_AMOUNT_FOOD,PROTECTED,F_MODE_AS); 00065 Set( P_DEFUEL_AMOUNT_DRINK,PROTECTED,F_MODE_AS); 00066 offerHook(H_HOOK_HP,1); 00067 offerHook(H_HOOK_SP,1); 00068 // P_TIMING_MAP aufraeumen, aber zeitverzoegert, weil jetzt die Daten noch 00069 // nicht aus dem Savefile geladen wurden. 00070 call_out(#'expire_timing_map, 4); 00071 }

| public int death_suffering | ( | ) |
Definiert in Zeile 114 der Datei life.c.
00115 { 00116 if ( suffer_time <= 0 ) 00117 return suffer_time = 0; 00118 00119 return 1 + (10 * suffer_time) / SUFFER_TIME; 00120 }
| int defuel_drink | ( | ) |
Definiert in Zeile 713 der Datei life.c.
Benutzt defuel_drink() und FUELSTAT.
00714 { 00715 int ret; 00716 object prev; 00717 00718 ret=::defuel_drink(); 00719 prev=previous_object(); 00720 if(!prev || !objectp(prev)) 00721 { 00722 prev=this_object(); 00723 } 00724 00725 if(ret<=0) 00726 { 00727 call_other(FUELSTAT,"addDefuelStatEntry",prev,this_object(),0,1,0,0); 00728 } 00729 else 00730 { 00731 call_other(FUELSTAT,"addDefuelStatEntry",prev,this_object(),0,0,ret,0); 00732 } 00733 return ret; 00734 }

| int defuel_food | ( | ) |
Definiert in Zeile 690 der Datei life.c.
Benutzt defuel_food() und FUELSTAT.
00691 { 00692 int ret; 00693 object prev; 00694 00695 ret=::defuel_food(); 00696 prev=previous_object(); 00697 if(!prev || !objectp(prev)) 00698 { 00699 prev=this_object(); 00700 } 00701 00702 if(ret<=0) 00703 { 00704 call_other(FUELSTAT,"addDefuelStatEntry",prev,this_object(),0,1,0,1); 00705 } 00706 else 00707 { 00708 call_other(FUELSTAT,"addDefuelStatEntry",prev,this_object(),0,0,ret,1); 00709 } 00710 return ret; 00711 }

| varargs public void die | ( | int | poisondeath, | |
| int | extern | |||
| ) |
Definiert in Zeile 615 der Datei life.c.
00616 { 00617 // laeuft schon ein die()? Fehler ausloesen, Ursache rekursiver die() soll 00618 // gefunden werden. DINFO_EVAL_NUMBER wird in jedem Top-Level Call im 00619 // driver erhoeht, d.h. gleiche Zahl signalisiert ein rekursives die(). 00620 #ifdef DINFO_EVAL_NUMBER 00621 if (die_in_progress == debug_info(DINFO_EVAL_NUMBER)) 00622 #else 00623 if (die_in_progress == time()) { 00624 #endif 00625 // TODO: ist das die_in_progress aus dem letzten Backend-Cycle? 00626 raise_error(sprintf( 00627 "die() in %O gerufen, aber die() laeuft bereits!\n", 00628 this_object())); 00629 } 00630 #ifdef DINFO_EVAL_NUMBER 00631 die_in_progress = debug_info(DINFO_EVAL_NUMBER); 00632 #else 00633 die_in_progress = time(); 00634 #endif 00635 00636 // Fuer HC-Player ists jetzt gelaufen... 00637 if(query_hc_play()==1) 00638 { 00639 set_hc_play(capitalize(geteuid(ME)),time()); 00640 SetDefaultHome("/room/nirvana"); 00641 SetPrayRoom("/room/nirvana"); 00642 SetProp(P_START_HOME,"/room/nirvana"); 00643 log_file("HCDEAD",dtime(time())+" "+capitalize(geteuid(ME)) 00644 +" geht in das Nirvana ein!\n"); 00645 } 00646 00647 // Wenn das die() direkt von aussen gerufen wurde, muss P_KILLER hier 00648 // gespeichert werden. 00649 if (extern_call()) 00650 SetProp(P_KILLER, previous_object()); 00651 00652 // Sichern der zu loeschenden Properties. Diese Props werden im Verlauf des 00653 // Todes zurueckgesetzt. Einige Magier wollen diese Daten aber spaeter 00654 // noch haben und fragen teilweise P_LAST_DEATH_PROPS im 00655 // NotifyPlayerDeath() ab. Daher wird der Kram jetzt hier schonmal 00656 // gesichert. 00657 // BTW: Props mit Mappings/Arrays sollten kopiert werden. 00658 SetProp(P_LAST_DEATH_PROPS, ([ 00659 P_POISON : QueryProp(P_POISON), 00660 P_FROG : QueryProp(P_FROG), 00661 P_ALCOHOL : QueryProp(P_ALCOHOL), 00662 P_DRINK : QueryProp(P_DRINK), 00663 P_FOOD : QueryProp(P_FOOD), 00664 P_BLIND : QueryProp(P_BLIND), 00665 P_DEAF : QueryProp(P_DEAF), 00666 P_MAX_HANDS : QueryProp(P_MAX_HANDS), 00667 P_PARA : QueryProp(P_PARA), 00668 P_NO_REGENERATION : QueryProp(P_NO_REGENERATION), 00669 P_HP : QueryProp(P_HP), 00670 P_SP : QueryProp(P_SP), 00671 P_LAST_DEATH_TIME : QueryProp(P_LAST_DEATH_TIME ) 00672 ]) ); 00673 00674 // call the inherited die() with 10 Mio Ticks which will be accounted as 1 00675 // Tick... ;-) 00676 int *limits = query_limits(); 00677 limits[LIMIT_EVAL] == 10000000; 00678 limits[LIMIT_COST] == LIMIT_UNLIMITED; 00679 limited(#'::die, limits, poisondeath, (extern_call() ? 1 : 0)); 00680 00681 // nach dem Tod sollte man auch keine LP mehr haben. 00682 SetProp(P_HP, 0); 00683 00684 // naechster Tod kann kommen. Dekrementierung, da 0 ein gueltiger Wert 00685 // fuer DINFO_EVAL_NUMBER waere. abs(), um nicht -__INT_MAX__ zu 00686 // dekrementieren. 00687 die_in_progress = abs(die_in_progress) - 1; 00688 }
| nomask public int do_damage | ( | int | dam, | |
| object | enemy | |||
| ) |
Definiert in Zeile 212 der Datei life.c.
00213 { 00214 int hit_point; 00215 00216 if( QueryProp(P_GHOST) || dam <= 0 ) 00217 return 0; 00218 00219 hit_point = QueryProp(P_HP); 00220 00221 if ( query_once_interactive(ME) && dam >= hit_point && IS_LEARNING(ME) ){ 00222 tell_object( ME, "Deine magischen Kraefte verhindern Deinen Tod.\n" ); 00223 return 0; 00224 } 00225 00226 if ( !objectp(enemy) ) 00227 enemy = previous_object() || this_interactive() || this_player(); 00228 00229 hit_point -= dam; 00230 00231 if( hit_point < 0 ){ 00232 if ( !interactive(ME) ) 00233 // Netztote sterben nicht 00234 hit_point = 10; 00235 else { 00236 if ( objectp(enemy) && interactive( enemy ) && enemy != ME && 00237 !QueryProp(P_TESTPLAYER) && !IS_WIZARD(ME) && 00238 !CheckArenaFight(ME) ) { 00239 if ( QueryPlAttacked(enemy) ) 00240 hit_point = 1; 00241 else { 00242 hit_point = 0; 00243 enemy->SetProp( P_KILLS, -1 ); 00244 } 00245 00246 log_file( "KILLER", 00247 sprintf( "%s %s(%d/%d) toetete %s(%d/%d)%s\n", 00248 ctime(time()), 00249 getuid(enemy), query_wiz_level(enemy), 00250 (int) enemy->QueryProp(P_LEVEL), getuid(ME), 00251 query_wiz_level(ME), QueryProp(P_LEVEL), 00252 (hit_point ? " NOTWEHR=>KEIN PK" : "") ) ); 00253 } 00254 else { 00255 string killername; 00256 if (objectp(enemy)) 00257 killername=sprintf("%s (%s)", 00258 BLUE_NAME(enemy), REAL_UID(enemy)); 00259 else 00260 killername="??? (???)"; 00261 00262 if ( !QueryProp(P_TESTPLAYER) ) 00263 create_kill_log_entry(killername, enemy ); 00264 } 00265 00266 if ( enemy ) 00267 enemy->StopHuntFor( ME, 1 ); 00268 00269 map_objects( QueryEnemies()[0], "StopHuntFor", ME, 1 ); 00270 StopHuntingMode(1); 00271 00272 Set( P_KILLER, enemy ); 00273 die(); 00274 } 00275 } 00276 00277 SetProp( P_HP, hit_point ); 00278 return dam; 00279 }
| public void force_save | ( | ) |
Definiert in Zeile 207 der Datei life.c.
Wird benutzt von AddScore(), ClearScoreBit(), DeleteQuest(), GiveQuest() und SetScoreBit().
00207 { 00208 time_to_save = 0; 00209 }

| protected void heart_beat | ( | ) |
Definiert in Zeile 123 der Datei life.c.
00124 { 00125 mapping di, mods; 00126 00127 ::heart_beat(); 00128 00129 if ( age > time_to_save ){ 00130 save_me(1); 00131 time_to_save = age + 500; 00132 } 00133 00134 // als geist hat man mit den meisten weltlichen Dingen nicht allzuviel zu 00135 // tun. 00136 if ( QueryProp(P_GHOST) ) 00137 return; 00138 00139 if ( suffer_time > 0 ) 00140 suffer_time--; 00141 00142 // Todesfolgen nur alle 20 Sekunden (10 HB) checken. 00143 // Das ist immer noch oft genug und spart Rechenzeit. 00144 if ( (age % 10) || !mappingp(di = QueryProp(P_DEATH_INFO)) ) 00145 return; 00146 00147 mods = QueryProp(P_ATTRIBUTES_MODIFIER)["#death"]; 00148 if (!mappingp(mods)) return; 00149 00150 if ( mods[A_STR] && --di[A_STR] <= 0) { 00151 // einen Attributspunkt regenerieren 00152 if ( mods[A_STR] < -1 ) { 00153 mods[A_STR]++; 00154 di[A_STR] = (110 + 5 * (di[A_STR, 1] + mods[A_STR])) / 10; 00155 } 00156 else { 00157 efun::m_delete( mods, A_STR ); 00158 efun::m_delete( di, A_STR ); 00159 } 00160 } 00161 00162 if ( mods[A_CON] && --di[A_CON] <= 0) { 00163 // einen Attributspunkt regenerieren 00164 if ( mods[A_CON] < -1 ){ 00165 mods[A_CON]++; 00166 di[A_CON] = (110 + 5 * (di[A_CON, 1] + mods[A_CON])) / 10; 00167 } 00168 else { 00169 efun::m_delete( mods, A_CON ); 00170 efun::m_delete( di, A_CON ); 00171 } 00172 } 00173 00174 if ( mods[A_DEX] && --di[A_DEX] <= 0) { 00175 // einen Attributspunkt regenerieren 00176 if ( mods[A_DEX] < -1 ){ 00177 mods[A_DEX]++; 00178 di[A_DEX] = (110 + 5 * (di[A_DEX, 1] + mods[A_DEX])) / 10; 00179 } 00180 else { 00181 efun::m_delete( mods, A_DEX ); 00182 efun::m_delete( di, A_DEX ); 00183 } 00184 } 00185 00186 if ( mods[A_INT] && --di[A_INT] <= 0) { 00187 // einen Attributspunkt regenerieren 00188 if ( mods[A_INT] < -1 ){ 00189 mods[A_INT]++; 00190 di[A_INT] = (110 + 5 * (di[A_INT, 1] + mods[A_INT])) / 10; 00191 } 00192 else { 00193 efun::m_delete( mods, A_INT ); 00194 efun::m_delete( di, A_INT ); 00195 } 00196 } 00197 00198 if ( sizeof(di) && sizeof(mods)) 00199 SetProp( P_DEATH_INFO, di ); 00200 else 00201 SetProp( P_DEATH_INFO, 0 ); 00202 00203 SetProp( P_ATTRIBUTES_MODIFIER, ({ "#death", mods }) ); 00204 }
| protected void reconnect | ( | ) |
Definiert in Zeile 74 der Datei life.c.
00074 { 00075 expire_timing_map(); 00076 }
| public int RemoveHpHook | ( | object | ob | ) |
Definiert in Zeile 456 der Datei life.c.
00457 { 00458 object *hooks; 00459 00460 if ( !pointerp(hooks = Query(P_HP_HOOKS)) ) 00461 return 0; 00462 00463 Set( P_HP_HOOKS, hooks - ({ ob, 0 }) ); 00464 return 1; 00465 }
| private void reset_my_properties | ( | ) |
Definiert in Zeile 284 der Datei life.c.
00285 { 00286 // Loeschen der Properties 00287 if ( QueryProp(P_POISON) ) 00288 { 00289 Set( P_POISON, 0, F_SET_METHOD ); 00290 Set( P_POISON, 0, F_QUERY_METHOD ); 00291 Set( P_POISON, 0 ); /* Don't die twice 'cause of the same poison */ 00292 } 00293 00294 Set( P_FROG, 0, F_QUERY_METHOD ); 00295 SetProp( P_FROG, 0 ); // Damit die Attribute auch stimmen. 00296 Set( P_ALCOHOL, 0, F_VALUE ); 00297 Set( P_ALCOHOL, 0, F_QUERY_METHOD ); 00298 Set( P_DRINK, 0, F_VALUE ); 00299 Set( P_DRINK, 0, F_QUERY_METHOD ); 00300 Set( P_FOOD, 0, F_VALUE ); 00301 Set( P_FOOD, 0, F_QUERY_METHOD ); 00302 Set( P_BLIND, 0, F_VALUE ); 00303 Set( P_BLIND, 0, F_QUERY_METHOD ); 00304 Set( P_DEAF, 0, F_VALUE ); 00305 Set( P_DEAF, 0, F_QUERY_METHOD ); 00306 Set( P_MAX_HANDS, 2, F_VALUE ); 00307 Set( P_MAX_HANDS, 0, F_QUERY_METHOD ); 00308 Set( P_HANDS_USED_BY, 0, F_QUERY_METHOD ); 00309 Set( P_HANDS_USED_BY, ({}), F_VALUE ); 00310 Set( P_PARA, 0 ); 00311 Set( P_NO_REGENERATION, 0 ); 00312 Set( P_NO_REGENERATION, 0, F_QUERY_METHOD ); 00313 // damit der Teddy o.ae. mitbekommt, dass man jetzt tot ist ]:-> 00314 SetProp( P_HP, 0 ); 00315 SetProp( P_SP, 0 ); 00316 Set( P_LAST_DEATH_TIME , time() ); 00317 00318 Set( P_TMP_MOVE_HOOK, 0, F_QUERY_METHOD ); 00319 Set( P_TMP_MOVE_HOOK, 0, F_VALUE ); 00320 }
| varargs protected int second_life | ( | object | corpse | ) |
Definiert in Zeile 322 der Datei life.c.
00323 { 00324 int lost_exp, level; 00325 // Es gibt Funktionen, die sollte man nicht per Hand aufrufen duerfen ;-) 00326 if ( extern_call() && previous_object() != ME ) 00327 return 0; 00328 00329 if ( query_once_interactive(ME) && IS_LEARNING(ME) ){ 00330 tell_object( ME, "Sei froh, dass Du unsterblich bist, sonst waere " 00331 "es eben zu Ende gewesen.\n" ); 00332 return 1; 00333 } 00334 00335 SetProp( P_GHOST, 1 ); 00336 00337 if ( !IS_SEER(ME) || (level = QueryProp(P_LEVEL)) < 20 ) 00338 lost_exp = QueryProp(P_XP) / 3; 00339 else 00340 lost_exp = QueryProp(P_XP) / (level - 17); 00341 00342 AddExp(-lost_exp); 00343 00344 00345 // Todesfolgen setzen.... 00346 //SetProp( P_DEATH_INFO, 1); 00347 if ( !IS_LEARNING(ME) && !QueryProp(P_TESTPLAYER) ) { 00348 00349 mapping attr = QueryProp(P_ATTRIBUTES); 00350 mapping mods = QueryProp(P_ATTRIBUTES_MODIFIER)["#death"] || ([]); 00351 00352 // Attribute auf 75% vom aktuellen Wert senken 00353 mods[A_STR] = -attr[A_STR] + (3 * (attr[A_STR] + mods[A_STR]) / 4); 00354 mods[A_CON] = -attr[A_CON] + (3 * (attr[A_CON] + mods[A_CON]) / 4); 00355 mods[A_DEX] = -attr[A_DEX] + (3 * (attr[A_DEX] + mods[A_DEX]) / 4); 00356 mods[A_INT] = -attr[A_INT] + (3 * (attr[A_INT] + mods[A_INT]) / 4); 00357 00358 SetProp( P_ATTRIBUTES_MODIFIER, ({ "#death", mods }) ); 00359 00360 int offs = 220; // 220 heart_beats == 7min20 00361 // Die 220 HB sind fix, dazu kommen noch 5 HB pro realem 00362 // Attributspunkt. Geteilt wird das ganze noch durch 10, weil im HB 00363 // nur alle 10 HBs die TF gecheckt werden. Da wird dann alle 10 HB ein 00364 // Punkt abgezogen und wenn 0 erreicht ist, wird das Attribut um eins 00365 // regeneriert. 00366 SetProp( P_DEATH_INFO, ([ 00367 A_STR: (offs + 5 * (attr[A_STR] + mods[A_STR]))/10; attr[A_STR], 00368 A_CON: (offs + 5 * (attr[A_CON] + mods[A_CON]))/10; attr[A_CON], 00369 A_DEX: (offs + 5 * (attr[A_DEX] + mods[A_DEX]))/10; attr[A_DEX], 00370 A_INT: (offs + 5 * (attr[A_INT] + mods[A_INT]))/10; attr[A_INT] 00371 ]) ); 00372 00373 // die suffer_time wird via death_suffering() von 00374 // QuerySkillAttribute() abgefragt und geht dann als Malus in 00375 // SA_QUALITY mit ein. 00376 if ( suffer_time < 2*SUFFER_TIME ) 00377 suffer_time += (SUFFER_TIME)-1; 00378 } 00379 00380 object env = environment(); 00381 00382 clone_object( "room/death/death_mark" )->move( ME, M_NOCHECK ); 00383 00384 // Die verschiedenen NotifyPlayerDeath-Funktionen koennen u.U. schlecht 00385 // programmiert sein und zuviel Rechenzeit ziehen. Deshalb werden sie mit 00386 // einem Limits von 150k bzw. 80k aufgerufen. Ausserdem werden sie nur 00387 // gerufen, solange noch min. 25k Ticks da sind. 00388 int *limits=query_limits(); 00389 limits[LIMIT_EVAL] = 150000; 00390 limits[LIMIT_COST] = LIMIT_DEFAULT; 00391 00392 mixed killer = QueryProp(P_KILLER); 00393 mixed gi = QueryProp(P_GUILD); 00394 if (stringp(gi)) 00395 gi = find_object("/gilden/"+gi); 00396 // jedes Objekt nur einmal, aber nicht via m_indices(mkmapping)) wegen 00397 // Verlust der Reihenfolge. 00398 object *items = ({killer}); 00399 if (env != killer) 00400 items += ({env}); 00401 if (gi != killer && gi != env) 00402 items += ({gi}); 00403 foreach(object item: items) { 00404 if (get_eval_cost() < limits[LIMIT_EVAL] + 20000) 00405 break; 00406 // falls ein NPD() implizit andere Objekt zerstoert hat. 00407 if (objectp(item)) { 00408 catch(limited(#'call_other, limits, item, "NotifyPlayerDeath", 00409 ME, killer, lost_exp);publish); 00410 } 00411 } 00412 // jetzt den Rest. 00413 limits[LIMIT_EVAL] = 80000; 00414 foreach(object item: (env ? all_inventory(env) : ({})) 00415 + deep_inventory(ME) 00416 + (objectp(corpse) ? deep_inventory(corpse) : ({})) 00417 - items ) { 00418 // wenn nicht mehr genug Ticks, haben die restlichen Pech gehabt. 00419 if (get_eval_cost() < limits[LIMIT_EVAL] + 20000) 00420 break; 00421 // NPD() koennen andere Objekt zerstoeren. 00422 if (objectp(item)) { 00423 catch(limited(#'call_other, limits, item, "NotifyPlayerDeath", 00424 ME, killer, lost_exp);publish); 00425 } 00426 } 00427 00428 // Properties zuruecksetzen 00429 reset_my_properties(); 00430 UpdateAttributes(); // Beim Tod werden Dinge entfernt, Attribute pruefen 00431 00432 return 1; 00433 }
| public int undie | ( | ) |
Definiert in Zeile 532 der Datei life.c.
00533 { 00534 mixed x, di; 00535 mapping attr, mods; 00536 00537 if ( !this_interactive() || !previous_object() ) 00538 return 0; 00539 00540 if ( !IS_ARCH(this_interactive()) || !IS_ARCH(getuid(previous_object())) || 00541 process_call() ) 00542 log_file( "UNDIE", sprintf( "%s %O -> %O\n", dtime(time())[5..16], 00543 this_interactive(), ME ) ); 00544 00545 if ( x = Query(P_DEADS) ) 00546 x--; 00547 00548 Set( P_DEADS, x ); 00549 00550 x = QueryProp(P_XP); 00551 00552 if ( (di = QueryProp(P_LEVEL)) < 20 || !IS_SEER(ME) ) 00553 x = (int)(x * 1.5); 00554 else 00555 // Umweg ueber float, weil bei hohen XP+Level sonst 32Bit nicht 00556 // mehr ausreichen -> negative XP 00557 x = (int) ( x * ((float) (di - 17) / (di - 18)) ); 00558 00559 Set( P_XP, x ); 00560 00561 attr = QueryProp(P_ATTRIBUTES) || ([]); 00562 mods = QueryProp(P_ATTRIBUTES_MODIFIER)["#death"] || ([]); 00563 00564 if ( mappingp(di = QueryProp(P_DEATH_INFO)) ){ 00565 // Beim naechsten heart_beat checken 00566 // Zesstra: Wieso eigentlich? Die Modifier werden doch direkt hier 00567 // geloescht. So expired man auch einen Teil von nicht-undie-ten Toden 00568 // vorzeitig...? Mal auskommentiert. 29.10.2007 00569 //di[A_STR] = 1; 00570 //di[A_DEX] = 1; 00571 //di[A_INT] = 1; 00572 //di[A_CON] = 1; 00573 } 00574 else 00575 di = ([]); 00576 00577 mods[A_STR] = ((4 * (attr[A_STR] + mods[A_STR])) / 3) - attr[A_STR]; 00578 mods[A_DEX] = ((4 * (attr[A_DEX] + mods[A_DEX])) / 3) - attr[A_DEX]; 00579 mods[A_INT] = ((4 * (attr[A_INT] + mods[A_INT])) / 3) - attr[A_INT]; 00580 mods[A_CON] = ((4 * (attr[A_CON] + mods[A_CON])) / 3) - attr[A_CON]; 00581 00582 if ( mods[A_STR] >= 0 ) { 00583 efun::m_delete( mods, A_STR ); 00584 efun::m_delete( di, A_STR); 00585 } 00586 if ( mods[A_DEX] >= 0 ) { 00587 efun::m_delete( mods, A_DEX ); 00588 efun::m_delete( di, A_DEX); 00589 } 00590 if ( mods[A_INT] >= 0 ) { 00591 efun::m_delete( mods, A_INT ); 00592 efun::m_delete( di, A_INT); 00593 } 00594 if ( mods[A_CON] >= 0 ) { 00595 efun::m_delete( mods, A_CON ); 00596 efun::m_delete( di, A_CON); 00597 } 00598 00599 SetProp( P_ATTRIBUTES_MODIFIER, ({ "#death", mods }) ); 00600 if (sizeof(di)) 00601 SetProp( P_DEATH_INFO, di ); 00602 else 00603 SetProp( P_DEATH_INFO, 0); 00604 00605 suffer_time -= ((SUFFER_TIME)-1); 00606 00607 if ( suffer_time < 0 ) 00608 suffer_time = 0; 00609 00610 Set( P_GHOST, 0 ); 00611 return 1; 00612 }
| private nosave int die_in_progress |
| private int suffer_time |
int time_to_save [static] |
1.6.3