combat.c-Dateireferenz

#include <sys_debug.h>
#include <debug_message.h>
#include <hook.h>
#include <living/skills.h>
#include <thing/properties.h>
#include <config.h>
#include <language.h>
#include <wizlevels.h>
#include <attributes.h>
#include <living.h>
#include <combat.h>
#include <doors.h>
#include <defines.h>
#include <new_skills.h>
#include <sensitive.h>
Include-Abhängigkeitsdiagramm für combat.c:

gehe zum Quellcode dieser Datei

Makrodefinitionen

#define NEED_PROTOTYPES
#define HUNTTIME   300
#define RNAME(x)   capitalize(getuid(x))
#define DEBUG(x)

Funktionen

private string _kill_alias (string str)
static void create ()
public void UpdateResistanceStrengths ()
public varargs int AddResistanceModifier (mapping mod, string add)
public varargs void RemoveResistanceModifier (string add)
static mixed _set_resistance (mixed arg)
static mixed _set_vulnerability (mixed arg)
public int Kill (object ob)
 kill - Kampf starten.
public int InsertSingleEnemy (object ob)
public int InsertEnemy (object ob)
public object QueryPreferedEnemy ()
public object * PresentEnemies ()
public varargs object SelectEnemy (object *here)
protected void heart_beat ()
protected void update_hunt_times (int beats)
public int IsEnemy (object wer)
public void StopHuntText (object arg)
public varargs int StopHuntFor (object arg, int silent)
public void Attack2 (object enemy)
protected void SkillResTransfer (mapping from_M, mapping to_M)
protected void InternalModifyAttack (mapping ainfo)
varargs public void ExtraAttack (object enemy, int ignore_previous)
public void Attack (object enemy)
public void AddDefender (object friend)
public void RemoveDefender (object friend)
public void InformDefend (object enemy)
public mixed DefendOther (int dam, mixed dam_type, mixed spell, object enemy)
public void CheckWimpyAndFlee ()
protected string mess (string msg, object me, object enemy)
protected void InternalModifyDefend (int dam, mixed dt, mapping spell, object enemy)
public int Defend (int dam, mixed dam_type, mixed spell, object enemy)
public float CheckResistance (string *dam_type)
public varargs mixed StopHuntingMode (int silent)
public mixed QueryEnemies ()
public mapping GetEnemies ()
public mapping SetEnemies (object *myenemies)
public varargs void Flee (object oldenv, int force)
public mixed EnemyPresent ()
public mixed InFight ()
public varargs int StopHuntID (string str, int silent)
public int SpellDefend (object caster, mapping sinfo)
static int _set_attack_busy (mixed val)
static int _query_attack_busy ()
static int _set_wimpy (int i)
static mixed _set_hands (mixed h)
static mixed _query_hands ()
static int _query_total_wc ()
static int _query_total_ac ()
static mapping _query_resistance_strengths ()
static int _set_disable_attack (int val)
static mixed * _query_hands_used_by ()
static int _query_used_hands ()
static int _query_free_hands ()
public varargs int UseHands (object ob, int num)
public varargs int FreeHands (object ob)
static int _set_used_hands (int new_num)
public int CheckEnemy (object ob)
public varargs void ExecuteMissingAttacks (object *remove_attackers)
public void InitAttack ()
public void ExitAttack ()
public mixed QueryArmourByType (string type)
static object * _set_armours (object *armours)
private void _decay_peace_history (mixed ph)
 Reduziert die Befriedezaehler pro Reset im Durchschnitt um 2.5.
public int Pacify (object caster)
 Pacify() dient zur Bestimmung, ob sich ein Lebewesen gerade befrieden lassen will.

Variablen

inherit std living inventory
inherit std living team
nosave mapping enemies
private nosave string magic_attack
private nosave int attack_busy
nosave int no_more_attacks
private nosave int remaining_heart_beats
private nosave int att2_time
private nosave string last_attack_msg
private nosave object * missing_attacks
private nosave mapping peace_tries
private nosave mapping QABTCache

Makro-Dokumentation

#define DEBUG ( x   ) 
Wert:
if (find_object("zesstra")) \
  tell_object(find_player("zesstra"),x)

Definiert in Zeile 78 der Datei combat.c.

#define HUNTTIME   300

Definiert in Zeile 35 der Datei combat.c.

Wird benutzt von heart_beat() und InsertSingleEnemy().

#define NEED_PROTOTYPES

Definiert in Zeile 18 der Datei combat.c.

#define RNAME ( x   )     capitalize(getuid(x))

Definiert in Zeile 36 der Datei combat.c.


Dokumentation der Funktionen

private void _decay_peace_history ( mixed  ph  ) 

Reduziert die Befriedezaehler pro Reset im Durchschnitt um 2.5.

Berechnet ganzzahlige durchschnittliche Resets seit dem letzten Expire und erhoeht die letzte Expirezeit um Resets*__RESET_TIME__ (Standard Intervall fuer Reset ist momentan 3600s, im Durchschnitt kommen dann 2700 zwischen 2 Resets bei raus). So wird der unganzzahlige Rest beim naechsten Aufruf beruecksichtigt. Diese Variante des Expires wurde gewaehlt, um zu vermeiden, combat.c einen reset() zu geben und in jedem Reset in jedem Lebewesen ein Expire machen zu muessen, auch wenn nur in sehr wenigen Lebewesen was gemacht werden muss.

Parameter:
[in,out] ph Mapping aus P_PEACE_HISTORY. Wird direkt aktualisiert.
Achtung:
Muss ein gueltiges P_PEACE_HISTORY uebergeben bekommen, anderem Datentyp inkl. 0 wird die Funktion buggen.

Definiert in Zeile 2144 der Datei combat.c.

Benutzt count und expire().

Wird benutzt von Pacify().

02144                                             {
02145   // Ganzzahlige resets seit letztem Expire ermitteln. (Durchschnitt)
02146   int resets = (time() - ph[0]) / (__RESET_TIME__*75/100);
02147   // auf Zeitstempel draufrechnen, damit der unganzzahlige Rest nicht
02148   // verlorengeht, der wird beim naechsten Expire dann beruecksichtigt.
02149   ph[0] += resets * (__RESET_TIME__ * 75 / 100);
02150   // pro Reset werden im Durchschnitt 2.5 Versuche abgezogen. (Hier werden
02151   // beim Expire mal 2 und mal 3 Versuche pro Reset gerechnet. Aber falls hier
02152   // viele Resets vergangen sind, ist es vermutlich eh egal, weil die Counter
02153   // auf 0 fallen.)
02154   int expire = resets * (random(2) + 2);
02155   // ueber alle Gilden
02156   mapping tmp=ph[1];
02157   foreach(string key, int count: &tmp ) {
02158     count-=expire;
02159     if (count < 0) count = 0;
02160   }
02161 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

private string _kill_alias ( string  str  ) 

Definiert in Zeile 1649 der Datei combat.c.

01650 {
01651     return "\\" + str;
01652 }

static int _query_attack_busy (  )  [static]

Definiert in Zeile 1799 der Datei combat.c.

Benutzt attack_busy, IS_LEARNING und ME.

01800 {
01801   if (IS_LEARNING(ME))
01802     return 0;
01803 
01804   return (attack_busy<100);
01805 }

static int _query_free_hands (  )  [static]

Definiert in Zeile 1936 der Datei combat.c.

Benutzt P_MAX_HANDS, P_USED_HANDS und QueryProp().

01937 {
01938   return (QueryProp(P_MAX_HANDS)-QueryProp(P_USED_HANDS));
01939 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static mixed _query_hands (  )  [static]

Definiert in Zeile 1824 der Datei combat.c.

Benutzt DT_BLUDGEON, P_HANDS, Query() und Set().

01825 {
01826   if ( !Query(P_HANDS) )
01827     return Set(P_HANDS, ({ " mit blossen Haenden", 30, DT_BLUDGEON }));
01828 
01829   return Query(P_HANDS);
01830 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static mixed* _query_hands_used_by (  )  [static]

Definiert in Zeile 1926 der Datei combat.c.

Benutzt F_VALUE, P_HANDS_USED_BY und Query().

01927 {
01928   return ((Query(P_HANDS_USED_BY, F_VALUE) || ({}) ) - ({0}));
01929 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static mapping _query_resistance_strengths (  )  [static]

Definiert in Zeile 1870 der Datei combat.c.

Benutzt P_RESISTANCE_MODIFIER, P_RESISTANCE_STRENGTHS, Query() und UpdateResistanceStrengths().

01870                                              {
01871 
01872   UpdateResistanceStrengths();
01873 
01874   mapping rstren = Query(P_RESISTANCE_STRENGTHS);
01875   mapping mod = Query(P_RESISTANCE_MODIFIER);
01876 
01877   if ( !mappingp(mod) || !mappingp(mod=mod["me"]) || !sizeof(mod) )
01878     return rstren;
01879 
01880   if ( mappingp(rstren) )
01881     rstren = deep_copy(rstren);
01882   else
01883     rstren = ([]);
01884 
01885   foreach(string modkey, float modvalue : mod)
01886     rstren[modkey] = ((1.0+rstren[modkey])*(1.0+modvalue))-1.0;
01887 
01888   return rstren;
01889 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _query_total_ac (  )  [static]

Definiert in Zeile 1849 der Datei combat.c.

Benutzt A_DEX, armour, armours, F_VALUE, P_AC, P_ARMOURS, P_BODY, P_PARRY_WEAPON, P_TOTAL_AC, QueryAttribute(), QueryProp() und Set().

01849                              {
01850 
01851   int totac = 0;
01852   object *armours = QueryProp(P_ARMOURS);
01853   object parry = QueryProp(P_PARRY_WEAPON);
01854 
01855   if ( member(armours,0)>=0 ) {
01856     armours -= ({ 0 }); 
01857   }
01858 
01859   foreach(object armour: armours)
01860     totac += ((int)armour->QueryProp(P_AC));
01861 
01862   if ( objectp(parry) )
01863     totac += parry->QueryProp(P_AC);
01864 
01865   totac += (QueryProp(P_BODY)+QueryAttribute(A_DEX));
01866 
01867   return Set(P_TOTAL_AC, totac, F_VALUE);
01868 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _query_total_wc (  )  [static]

Definiert in Zeile 1832 der Datei combat.c.

Benutzt A_STR, F_VALUE, P_HANDS, P_TOTAL_WC, P_WC, P_WEAPON, QueryAttribute(), QueryProp() und Set().

01833 { mixed res;
01834   int   totwc;
01835 
01836   if ( objectp(res=QueryProp(P_WEAPON)) )
01837     totwc = ((int)(res->QueryProp(P_WC)));
01838   else if ( pointerp(res=QueryProp(P_HANDS)) && sizeof(res)>1
01839            && intp(res[1]) )
01840     totwc=((int)res[1]);
01841   else
01842     totwc=30;
01843 
01844   totwc = ((2*totwc)+(10*QueryAttribute(A_STR)))/3;
01845 
01846   return Set(P_TOTAL_WC, totwc, F_VALUE);
01847 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _query_used_hands (  )  [static]

Definiert in Zeile 1931 der Datei combat.c.

Benutzt P_HANDS_USED_BY und QueryProp().

01932 {
01933   return sizeof(QueryProp(P_HANDS_USED_BY));
01934 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static object* _set_armours ( object *  armours  )  [static]

Definiert in Zeile 2121 der Datei combat.c.

Benutzt F_VALUE, P_ARMOURS, QABTCache, QueryProp() und Set().

02121                                              {
02122   if (pointerp(armours)) {
02123     // Cache wegwerfen
02124     QABTCache = 0;
02125     // armours ggf. unifizieren. Ausserdem Kopie reinschreiben.
02126     return Set(P_ARMOURS, m_indices(mkmapping(armours)), F_VALUE);
02127   }
02128   return QueryProp(P_ARMOURS);
02129 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _set_attack_busy ( mixed  val  )  [static]

Definiert in Zeile 1784 der Datei combat.c.

Benutzt attack_busy, dtime() und log_file.

01785 {
01786   if ( ((to_int(val))>5) && previous_object(1)
01787       && query_once_interactive(previous_object(1)) )
01788     log_file("ATTACKBUSY",sprintf("%s %d Taeter: %O Opfer: %O\n",
01789              dtime(time()),to_int(val),previous_object(1),this_object()));
01790 
01791   attack_busy-=to_int(val*100.0);
01792 
01793   if ( attack_busy<-2000 )
01794     attack_busy=-2000;
01795 
01796   return attack_busy;
01797 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _set_disable_attack ( int  val  )  [static]

Definiert in Zeile 1891 der Datei combat.c.

Benutzt ctime(), DISABLE_TOO_EARLY, log_file, ME, P_DISABLE_ATTACK, P_NEXT_DISABLE_ATTACK, QueryProp(), Set() und SetProp().

01892 {
01893   if (val<-100000)
01894                    {
01895                                 log_file("PARALYSE_TOO_LOW",
01896                                                   sprintf("Wert zu klein: %s, Wert: %d, "
01897                                                                   "Aufrufer: %O, Opfer: %O",
01898                                                                   ctime(time()),
01899                                                                                   val,previous_object(1),
01900                                                                                   this_object()));
01901                    }
01902   if ( val>30 )
01903     val=30;
01904   if ( (val>=20) && previous_object(1) && query_once_interactive(ME) )
01905     log_file("PARALYSE",sprintf("%s %d Taeter: %O Opfer: %O\n",
01906                                 ctime(time())[4..15],
01907                                 val,previous_object(1),this_object()));
01908   // Neu: Disable Attack nur noch wenn innerhalb der letzten
01909   // Zeit kein Disable Attack aufgerufen wurde
01910   // UND natuerlich nur, wenn der Wert HOCH gesetzt wird
01911   if (time()<QueryProp(P_NEXT_DISABLE_ATTACK) && (val>0)
01912                                   && val>=QueryProp(P_DISABLE_ATTACK))
01913   {
01914                 return DISABLE_TOO_EARLY;
01915   }
01916 
01917   SetProp(P_NEXT_DISABLE_ATTACK,time()+val*4);
01918   return Set(P_DISABLE_ATTACK,val);
01919 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static mixed _set_hands ( mixed  h  )  [static]

Definiert in Zeile 1816 der Datei combat.c.

Benutzt DT_BLUDGEON, P_HANDS und Set().

01817 { 
01818   if ( sizeof(h)==2 )
01819     h += ({ DT_BLUDGEON });
01820 
01821   return Set(P_HANDS, h);
01822 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static mixed _set_resistance ( mixed  arg  )  [static]

Definiert in Zeile 163 der Datei combat.c.

Benutzt i, P_RESISTANCE, P_RESISTANCE_STRENGTHS, Query(), QueryProp(), Set() und SetProp().

00164 { int     i;
00165   mapping resimap;
00166   mixed   old;
00167 
00168   if ( !pointerp(arg) )
00169     arg=({arg});
00170 
00171   if ( !mappingp(resimap=Query(P_RESISTANCE_STRENGTHS)) )
00172     resimap=([]);
00173 
00174   if ( pointerp(old=QueryProp(P_RESISTANCE)) )
00175     for ( i=sizeof(old)-1 ; i>=0 ; i-- )
00176       resimap[old[i]]=(1.0+((float)resimap[old[i]]))*2.0-1.0;
00177 
00178   for ( i=sizeof(arg)-1 ; i>=0 ; i-- )
00179     resimap[arg[i]]=(1.0+((float)resimap[arg[i]]))*0.5-1.0;
00180 
00181   SetProp(P_RESISTANCE_STRENGTHS,resimap);
00182 
00183   return Set(P_RESISTANCE,arg);
00184 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _set_used_hands ( int  new_num  )  [static]

Definiert in Zeile 1975 der Datei combat.c.

Benutzt DMSG_LOGFILE, DMSG_STAMP, FreeHands(), ob(), P_USED_HANDS, QueryProp() und UseHands().

01976 { int    old_num, dif;
01977   object ob;
01978 
01979   old_num=QueryProp(P_USED_HANDS);
01980 
01981   if ( !objectp(ob=previous_object(1)) )
01982     return old_num;
01983 
01984   // Meldung ins Debuglog schreiben. Aufrufer sollte gefixt werden.
01985   debug_message(sprintf("P_USED_HANDS in %O wird gesetzt durch %O\n",
01986         this_object(), ob), DMSG_LOGFILE|DMSG_STAMP);
01987 
01988   if ( !(dif=new_num-old_num) )
01989     return new_num;
01990 
01991   if ( dif>0 )
01992     UseHands(ob,dif);
01993   else
01994     FreeHands(ob);
01995 
01996   return QueryProp(P_USED_HANDS);
01997 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static mixed _set_vulnerability ( mixed  arg  )  [static]

Definiert in Zeile 187 der Datei combat.c.

Benutzt i, P_RESISTANCE_STRENGTHS, P_VULNERABILITY, Query(), QueryProp(), Set() und SetProp().

00188 { int     i;
00189   mapping resimap;
00190   mixed   old;
00191 
00192   if ( !pointerp(arg) )
00193     arg=({arg});
00194 
00195   if ( !mappingp(resimap=Query(P_RESISTANCE_STRENGTHS)) )
00196     resimap=([]);
00197 
00198   if ( pointerp(old=QueryProp(P_VULNERABILITY)) )
00199     for ( i=sizeof(old)-1 ; i>=0 ; i-- )
00200       resimap[old[i]]=(1.0+((float)resimap[old[i]]))*0.5-1.0;
00201 
00202   for ( i=sizeof(arg)-1 ; i>=0 ; i-- )
00203     resimap[arg[i]]=(1.0+((float)resimap[arg[i]]))*2.0-1.0;
00204 
00205   SetProp(P_RESISTANCE_STRENGTHS,resimap);
00206 
00207   return Set(P_VULNERABILITY,arg);
00208 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static int _set_wimpy ( int  i  )  [static]

Definiert in Zeile 1808 der Datei combat.c.

Benutzt P_MAX_HP, P_WIMPY, QueryProp() und Set().

01809 {
01810   if ( !intp(i) || (i>QueryProp(P_MAX_HP)) || (i<0) )
01811     return 0;
01812 
01813   return Set(P_WIMPY, i);
01814 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public void AddDefender ( object  friend  ) 

Definiert in Zeile 878 der Datei combat.c.

Benutzt P_DEFENDERS, QueryProp() und SetProp().

00879 { object *defs;
00880 
00881   if ( !objectp(friend) )
00882     return;
00883 
00884   if ( !pointerp(defs=QueryProp(P_DEFENDERS)) )
00885     defs=({});
00886 
00887   if ( member(defs,friend)>=0 )
00888     return;
00889 
00890   defs+=({friend});
00891   SetProp(P_DEFENDERS,defs);
00892 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public varargs int AddResistanceModifier ( mapping  mod,
string  add 
)

Definiert in Zeile 116 der Datei combat.c.

Benutzt P_RESISTANCE_MODIFIER, Query(), Set() und UpdateResistanceStrengths().

00117 { string  key;
00118   mapping res;
00119 
00120   if ( !mappingp(mod) || !sizeof(mod) || !previous_object() )
00121     return 0;
00122 
00123   key = explode(object_name(previous_object()),"#")[0];
00124 
00125   if ( add )
00126     key += ("#"+add);
00127 
00128   res = Query(P_RESISTANCE_MODIFIER);
00129   mod = deep_copy(mod);
00130 
00131   if ( !mappingp(res) )
00132     res = ([ key : mod; previous_object() ]);
00133   else
00134     res += ([ key : mod; previous_object() ]);
00135 
00136   Set(P_RESISTANCE_MODIFIER, res);
00137   UpdateResistanceStrengths();
00138 
00139   return 1;
00140 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public void Attack ( object  enemy  ) 

Definiert in Zeile 645 der Datei combat.c.

Benutzt A_STR, cl, CURRENT_DAM, CURRENT_DAMTYPE, EINFO_DEFEND, FIGHT, H_ALTERED, H_CANCELLED, H_HOOK_ATTACK, H_HOOK_ATTACK_MOD, H_RETCODE, H_RETDATA, HookFlow(), InternalModifyAttack(), last_attack_msg, ME, Name(), no_more_attacks, ORIGINAL_AINFO, ORIGINAL_DAM, ORIGINAL_DAMTYPE, P_DAM_TYPE, P_DISABLE_ATTACK, P_GHOST, P_HANDS, P_LAST_COMBAT_TIME, P_MAX_HANDS, P_NO_ATTACK, P_PLURAL, P_SHOW_ATTACK_MSG, P_TMP_ATTACK_HOOK, P_TMP_ATTACK_MOD, P_USED_HANDS, P_WC, P_WEAPON, P_WEAPON_TYPE, Query(), QueryAttribute(), QueryDamage(), QueryProp(), Set(), SetProp(), SI_ENEMY, SI_SKILLDAMAGE, SI_SKILLDAMAGE_MSG, SI_SKILLDAMAGE_MSG2, SI_SKILLDAMAGE_TYPE, SI_SPELL, SK_FIGHT, SK_MAGIC_ATTACK, SK_TWOHANDED, SkillResTransfer(), SP_PHYSICAL_ATTACK, SP_REDUCE_ARMOUR, SP_SHOW_DAMAGE, UseSkill(), WEM, WEN, WER, WT_HANDS und WT_MAGIC.

Wird benutzt von Attack(), Attack2(), ExtraAttack() und heart_beat().

00646 {
00647   closure cl;
00648   mixed   res;
00649   mapping ainfo;
00650   mapping edefendinfo; // erweiterte Defend-Infos
00651   mixed hookData;
00652   mixed hookRes;
00653 
00654   if ( no_more_attacks || QueryProp(P_GHOST) || 
00655       !objectp(enemy) || !objectp(this_object()) || 
00656       (QueryProp(P_DISABLE_ATTACK) > 0) || enemy->QueryProp(P_NO_ATTACK) || 
00657       (query_once_interactive(this_object()) && !interactive(this_object())) )
00658     return;
00659 
00660   edefendinfo=([]);
00661 
00662   Set(P_LAST_COMBAT_TIME,time());
00663 
00664   // inkrementieren. Diese Variable wird im HB nach den Angriffen genullt.
00665   // Diese Variable wird im naechsten Heartbeat von der Anzahl an verfuegbaren
00666   // Angriffen des Livings abgezogen. Dies beruecksichtigt also zwischen den
00667   // HBs (z.B. extern) gerufene Attacks().
00668   no_more_attacks++;
00669 
00670   // Wird das Attack durch einen temporaeren Attack-Hook ersetzt?
00671   if ( res=QueryProp(P_TMP_ATTACK_HOOK) )
00672   {
00673     if ( pointerp(res) && (sizeof(res)>=3) && intp(res[0]) && (time()<res[0])
00674         && objectp(res[1]) && stringp(res[2]) )
00675     {
00676       if ( !(res=call_other(res[1],res[2],enemy)) )
00677         return;
00678     }
00679     else
00680       SetProp(P_TMP_ATTACK_HOOK,0);
00681   }
00682 
00683   // trigger attack hook
00684   hookData=({enemy});
00685   hookRes=HookFlow(H_HOOK_ATTACK,hookData);
00686   if(hookRes && pointerp(hookRes) && sizeof(hookRes)>H_RETDATA){
00687     if(hookRes[H_RETCODE]==H_CANCELLED){
00688       return;
00689     }
00690   }
00691 
00692   ainfo = ([ SI_ENEMY : enemy,
00693              SI_SPELL : 0,
00694            ]);
00695 
00696   if ( objectp(ainfo[P_WEAPON]=QueryProp(P_WEAPON)) )
00697   {
00698     ainfo[P_WEAPON]->TakeFlaw(enemy);
00699 
00700     // Abfrage fuer den Fall, dass Waffe durch das TakeFlaw() zerstoert
00701     // wurde. Dann wird das Attack abgebrochen.
00702     if ( !objectp(ainfo[P_WEAPON]) )
00703       return;
00704 
00705     cl=symbol_function("name",ainfo[P_WEAPON]);
00706     ainfo[SI_SKILLDAMAGE_MSG] = (" mit "+(string)funcall(cl,WEM,0));
00707     ainfo[SI_SKILLDAMAGE_MSG2] = (" mit "+(string)funcall(cl,WEM,1));
00708 
00709     ainfo[SI_SKILLDAMAGE] = (int)ainfo[P_WEAPON]->QueryDamage(enemy);
00710 
00711     cl=symbol_function("QueryProp",ainfo[P_WEAPON]);
00712     ainfo[SI_SKILLDAMAGE_TYPE] = funcall(cl,P_DAM_TYPE);
00713     ainfo[P_WEAPON_TYPE] = (string)funcall(cl,P_WEAPON_TYPE);
00714     ainfo[P_NR_HANDS] = (int)funcall(cl,P_NR_HANDS);
00715     ainfo[P_WC] = (int)funcall(cl,P_WC);
00716 
00717     // Zweihaendige Waffe?
00718     if ( ainfo[P_NR_HANDS]==2
00719         && mappingp(res=UseSkill(SK_TWOHANDED,deep_copy(ainfo)))
00720         && member(res,SI_SKILLDAMAGE) )
00721     {
00722       // Nur den neuen Schadenswert uebernehmen.
00723       ainfo[SI_SKILLDAMAGE]=((int)(res[SI_SKILLDAMAGE]));
00724     }
00725   }
00726   else // Keine Waffe gezueckt
00727   {
00728     /* Check if there is a magical attack */
00729     if ( mappingp(res=UseSkill(SK_MAGIC_ATTACK,([SI_ENEMY:enemy]))) )
00730     {
00731       ainfo[SI_SKILLDAMAGE]=(int)res[SI_SKILLDAMAGE];
00732       ainfo[SI_SKILLDAMAGE_TYPE]=res[SI_SKILLDAMAGE_TYPE];
00733 
00734       if ( stringp(res[SI_SKILLDAMAGE_MSG]) )
00735         ainfo[SI_SKILLDAMAGE_MSG] = " mit "+(string)res[SI_SKILLDAMAGE_MSG];
00736       else
00737         ainfo[SI_SKILLDAMAGE_MSG] = " mit magischen Faehigkeiten";
00738 
00739       if ( stringp(res[SI_SKILLDAMAGE_MSG2]) )
00740         ainfo[SI_SKILLDAMAGE_MSG2] = " mit "+(string)res[SI_SKILLDAMAGE_MSG2];
00741       else
00742         ainfo[SI_SKILLDAMAGE_MSG2] = (string)ainfo[SI_SKILLDAMAGE_MSG];
00743 
00744       if ( !(ainfo[P_WEAPON_TYPE]=res[P_WEAPON_TYPE]) )
00745         ainfo[P_WEAPON_TYPE]=WT_MAGIC;
00746 
00747       if ( member(res,SI_SPELL) )
00748         ainfo[SI_SPELL]=res[SI_SPELL];
00749     }
00750     else
00751     {
00752       /* Ohne (freie) Haende wird auch nicht angegriffen */
00753       if ( interactive(this_object())
00754           && (QueryProp(P_USED_HANDS) >= QueryProp(P_MAX_HANDS)) )
00755         return ;
00756 
00757       if ( !pointerp(res=QueryProp(P_HANDS)) || (sizeof(res)<2) )
00758         return;
00759 
00760       ainfo[SI_SKILLDAMAGE] = (( 2*random(((int)res[1])+1)
00761                               + 10*(QueryAttribute(A_STR)) )/3);
00762       ainfo[SI_SKILLDAMAGE_TYPE] = res[2];
00763       ainfo[SI_SKILLDAMAGE_MSG] = ainfo[SI_SKILLDAMAGE_MSG2]
00764                                 = ((string)res[0]);
00765       ainfo[P_WEAPON_TYPE] = WT_HANDS;
00766       ainfo[P_WC] = (int)res[1];
00767     }
00768   }  // besondere Faehigkeiten mit diesem Waffentyp?
00769   if ( mappingp(res=UseSkill(FIGHT(ainfo[P_WEAPON_TYPE]),
00770                              deep_copy(ainfo))) )
00771     SkillResTransfer(res,ainfo);
00772 
00773   // besondere allgemeine Kampffaehigkeiten?
00774   if ( mappingp(res=UseSkill(SK_FIGHT,deep_copy(ainfo))) )
00775     SkillResTransfer(res,ainfo);
00776 
00777   // Veraenderungen durch einen Attack-Modifier?
00778   if ( (res=QueryProp(P_TMP_ATTACK_MOD)) )
00779   {
00780     if ( pointerp(res) && (sizeof(res)>=3) && intp(res[0])
00781         && (time()<res[0]) && objectp(res[1]) && stringp(res[2]) )
00782     {
00783       if ( !(res=call_other(res[1],res[2],deep_copy(ainfo)))
00784           || !mappingp(res) )
00785         return;
00786       else
00787         SkillResTransfer(res,ainfo);
00788     }
00789     else
00790       SetProp(P_TMP_ATTACK_MOD,0);
00791   }
00792 
00793   // trigger attack mod hook
00794   hookData=deep_copy(ainfo);
00795   hookRes=HookFlow(H_HOOK_ATTACK_MOD,hookData);
00796   if(hookRes && pointerp(hookRes) && sizeof(hookRes)>H_RETDATA){
00797     if(hookRes[H_RETCODE]==H_CANCELLED){
00798       return;
00799     }
00800     else if(hookRes[H_RETCODE]==H_ALTERED && hookRes[H_RETDATA] &&
00801              mappingp(hookRes[H_RETDATA])){
00802         SkillResTransfer(hookRes[H_RETDATA],ainfo);
00803     }
00804   }
00805 
00806   // Interne Modifikationen der Angriffswerte
00807   InternalModifyAttack(ainfo);
00808 
00809   if ( !objectp(enemy) )
00810     return;
00811 
00812   // hier mal bewusst nicht auf P_PLURAL zuerst testen. in 90% der Faelle
00813   // wird eh keine Angriffsmeldung mehr ausgegeben, also pruefen wir das
00814   // lieber zuerst. Plural testen zieht schon genug Rechenzeit :/
00815   // Nicht meine Idee! Nicht meine Idee! Nachtwind 7.7.2001
00816   if ( ainfo[SI_SKILLDAMAGE_MSG2]!=last_attack_msg )
00817   {
00818     last_attack_msg = ainfo[SI_SKILLDAMAGE_MSG2];
00819     if (QueryProp(P_PLURAL))
00820     {
00821       tell_object( ME, "  Ihr greift " + enemy->name(WEN,1)
00822                    + ainfo[SI_SKILLDAMAGE_MSG2] + " an.\n" );
00823       say("  "+(Name(WER,1))+" greifen "+(enemy->name(WEN,1))+
00824           ainfo[SI_SKILLDAMAGE_MSG]+" an.\n", enemy );
00825       tell_object( enemy, "  "+(Name(WER,1))+" greifen "+
00826                   (enemy->QueryProp(P_PLURAL)?"Euch":"Dich")+
00827                    ainfo[SI_SKILLDAMAGE_MSG2]+" an.\n" );
00828     }
00829     else
00830     {
00831       tell_object( ME, "  Du greifst " + enemy->name(WEN,1)
00832                    + ainfo[SI_SKILLDAMAGE_MSG2] + " an.\n" );
00833       say("  "+(Name(WER,2))+" greift "+(enemy->name(WEN,1))+
00834           ainfo[SI_SKILLDAMAGE_MSG]+" an.\n", enemy );
00835       tell_object( enemy, "  "+(Name(WER,1))+" greift "+
00836                   (enemy->QueryProp(P_PLURAL)?"Euch":"Dich")+
00837                    ainfo[SI_SKILLDAMAGE_MSG2]+" an.\n" );    }
00838   }
00839   else if ( Query(P_SHOW_ATTACK_MSG) )
00840     if (QueryProp(P_PLURAL))
00841       tell_object( ME, "  Ihr greift " + enemy->name(WEN,1)
00842                    + ainfo[SI_SKILLDAMAGE_MSG2] + " an.\n" );
00843     else
00844       tell_object( ME, "  Du greifst " + enemy->name(WEN,1)
00845                    + ainfo[SI_SKILLDAMAGE_MSG2] + " an.\n" );
00846 
00847   // ainfo in defendinfo merken
00848   edefendinfo[ ORIGINAL_AINFO]= deep_copy(ainfo);
00849   edefendinfo[ ORIGINAL_DAM]= ainfo[SI_SKILLDAMAGE];
00850   edefendinfo[ ORIGINAL_DAMTYPE]= ainfo[SI_SKILLDAMAGE_TYPE];
00851   edefendinfo[ CURRENT_DAM]= ainfo[SI_SKILLDAMAGE];
00852   edefendinfo[ CURRENT_DAMTYPE]= ainfo[SI_SKILLDAMAGE_TYPE];
00853 
00854   // ainfo[SI_SPELL] auf ein mapping normieren
00855   if ( intp(ainfo[SI_SPELL]) )
00856   {
00857     ainfo[SI_SPELL] = ([ SP_PHYSICAL_ATTACK : !ainfo[SI_SPELL],
00858                SP_SHOW_DAMAGE     : !ainfo[SI_SPELL],
00859                SP_REDUCE_ARMOUR   : ([ ])  ]);
00860   }
00861 
00862   // defendinfo anhaengen, falls ainfo[SI_SPELL] ein mapping ist
00863   if( mappingp(ainfo[SI_SPELL]))
00864   {
00865     ainfo[SI_SPELL][EINFO_DEFEND]=edefendinfo;
00866   }
00867 
00868 
00869   enemy->Defend(ainfo[SI_SKILLDAMAGE], ainfo[SI_SKILLDAMAGE_TYPE],
00870                 ainfo[SI_SPELL],       this_object());
00871 
00872 
00873   //edefendinfo=([]);
00874 
00875   /* Done attacking */
00876 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public void Attack2 ( object  enemy  ) 

Definiert in Zeile 566 der Datei combat.c.

Benutzt att2_time und Attack().

Wird benutzt von InitAttack().

00567 {
00568   if ( att2_time > time() )
00569     return;
00570 
00571   att2_time=time() + __HEART_BEAT_INTERVAL__;
00572   Attack(enemy);
00573 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public int CheckEnemy ( object  ob  ) 

Definiert in Zeile 2001 der Datei combat.c.

Benutzt IsEnemy().

02002 {
02003   return (living(ob) && IsEnemy(ob));
02004 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public float CheckResistance ( string *  dam_type  ) 

Definiert in Zeile 1571 der Datei combat.c.

01571                                                {
01572     //funktion kriegt die schadensarten uebergeben, schaut sich dieses
01573     //sowie P_RESISTENCE_STRENGTH und P_RESITENCE_MODFIFIER an und berechnet
01574     //einen Faktor, mit dem die urspruengliche Schadensmenge multipliziert
01575     //wird, um den Schaden nach Beruecksichtigung der Resis/Anfaelligkeiten zu
01576     //erhalten. Rueckgabewert normalerweise (s.u.) >=0.
01577   mapping rstren, mod;
01578   float   faktor,n;
01579   int     i;
01580 
01581   mod = Query(P_RESISTANCE_MODIFIER);
01582   if ( mappingp(mod) )
01583     mod = mod["me"];
01584 
01585   if ( !mappingp(rstren=Query(P_RESISTANCE_STRENGTHS)) )
01586   {
01587     if (!mappingp(mod))
01588       return 1.0;
01589     else
01590       rstren = ([]);
01591   }
01592 
01593   if ( !mappingp(mod) )
01594     mod = ([]);
01595 
01596   if (!pointerp(dam_type))
01597   {
01598     log_file("bad_damage",
01599              sprintf ("in %O\n\t%O\n",this_object(),dam_type));
01600     dam_type=({dam_type});
01601   }
01602 
01603   if ( (i=sizeof(dam_type))<1 )
01604     return 1.0;
01605 
01606   n=to_float(i);
01607   faktor=0.0;
01608 
01609   //dies hier tut nicht mehr das gewuenschte, wenn in P_RESISTENCE_STRENGTHS
01610   //Faktoren <-1.0 angegeben werden. Rueckgabewerte <0 sind dann moeglich und
01611   //leider werden die Schadensarten ohne Resis nicht mehr richtig verwurstet. :-/
01612   foreach(string dt: dam_type) {
01613     faktor = faktor + (1.0 + to_float(rstren[dt]))
01614            * (1.0 + to_float(mod[dt]))-1.0;
01615   }
01616   return 1.0+(faktor/n);
01617 }

public void CheckWimpyAndFlee (  ) 

Definiert in Zeile 933 der Datei combat.c.

Benutzt call_out(), P_HP, P_WIMPY, QueryProp() und TeamFlee().

00934 {
00935   if ( (QueryProp(P_WIMPY)>QueryProp(P_HP)) && !TeamFlee()
00936       && find_call_out("Flee")<0 )
00937     call_out(#'Flee,0,environment());
00938 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

static void create (  )  [static]

Definiert in Zeile 54 der Datei combat.c.

Benutzt att2_time, attack_busy, create(), enemies, F_MODE_AS, H_HOOK_ATTACK, H_HOOK_ATTACK_MOD, H_HOOK_DEFEND, offerHook(), P_ARMOURS, P_GUILD_PREPAREBLOCK, P_HANDS, P_RESISTANCE, P_SHOW_ATTACK_MSG, P_TOTAL_AC, P_VULNERABILITY, P_WIMPY, peace_tries, PROTECTED, SAVE, Set() und SetProp().

00055 {
00056   Set(P_WIMPY, SAVE, F_MODE_AS);
00057   Set(P_TOTAL_AC, PROTECTED, F_MODE_AS);
00058   Set(P_HANDS, SAVE, F_MODE_AS);
00059   Set(P_SHOW_ATTACK_MSG,SAVE,F_MODE_AS);
00060   Set(P_RESISTANCE, ({}));
00061   Set(P_VULNERABILITY, ({}));
00062   Set(P_GUILD_PREPAREBLOCK, SAVE, F_MODE_AS);
00063   // Kein Setzen von P_ARMOURS von aussen per Set(). (Per SetProp() geht es
00064   // durch die Setmethode).
00065   Set(P_ARMOURS,PROTECTED,F_MODE_AS);
00066   SetProp(P_ARMOURS, ({}));
00067   attack_busy=100;
00068   att2_time=0;
00069   enemies=([]);
00070   peace_tries=([]);
00071   team::create(); 
00072   offerHook(H_HOOK_DEFEND,1);
00073   offerHook(H_HOOK_ATTACK,1);
00074   offerHook(H_HOOK_ATTACK_MOD,1);
00075 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public int Defend ( int  dam,
mixed  dam_type,
mixed  spell,
object  enemy 
)

Definiert in Zeile 975 der Datei combat.c.

Wird benutzt von Defend().

00976 {
00977   int     i,k;
00978   mixed   res,res2;
00979   object  *armours,tmp;
00980   mixed hookData;
00981   mixed hookRes;
00982   
00983   //  string  what, how;
00984   string enname, myname;
00985 
00986   // Testen, ob dieses Lebewesen ueberhaupt angegriffen werden darf
00987   if ( !(enemy=(enemy||this_player())) || QueryProp(P_NO_ATTACK)
00988       || ( query_once_interactive(enemy) && ! interactive(enemy) ) )
00989     return 0;
00990 
00991   if ( intp(spell) )
00992     spell = ([ SP_PHYSICAL_ATTACK : !spell,
00993                SP_SHOW_DAMAGE     : !spell,
00994                SP_REDUCE_ARMOUR   : ([ ])  ]);
00995   else if ( !mappingp(spell) ) // Illegaler spell-Parameter
00996     return 0;
00997 
00998   // testen ob eine erweiterte defendinfo vorhanden ist
00999   if(!member(spell,EINFO_DEFEND))
01000   {
01001                 //spell+=([EINFO_DEFEND:([])]); // ggf hinzufuegen
01002                 // use a temporary mapping to avoid recursive
01003                 // val[x][y] = deep_copy(val);
01004                 mapping tmpdefend = ([
01005                                 ORIGINAL_AINFO:deep_copy(spell),
01006                                 ORIGINAL_DAM:dam,
01007                                 ORIGINAL_DAMTYPE:dam_type,
01008                 ]);
01009                 spell[EINFO_DEFEND]=tmpdefend;
01010   }
01011 
01012   // Schadenstyp ueberpruefen
01013   if ( !pointerp(dam_type) )
01014     dam_type = ({ dam_type });
01015 
01016   spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
01017   spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01018 
01019   // Testen, ob der Angreifer schon als Feind registriert worden ist.
01020   // Wenn nein, registrieren.
01021   if ( !IsEnemy(enemy) && !spell[SP_NO_ENEMY] )
01022   {
01023     spell[EINFO_DEFEND][ENEMY_INSERTED]=1;
01024     InsertEnemy(enemy);
01025   }
01026 
01027   // RFR-Taktik abfangen
01028   if ( !QueryProp(P_ENABLE_IN_ATTACK_OUT) )
01029   {
01030     i=time()-(enemy->QueryProp(P_LAST_MOVE));
01031     // Gegner hat sich bewegt, man selbst nicht
01032     if ( (i<3) && (time()-QueryProp(P_LAST_MOVE)>=5) )
01033     {
01034       // Bei Erster Kampfrunde wenige Schaden
01035       dam/=(4-i);
01036       spell[EINFO_DEFEND][RFR_REDUCE]=dam;
01037       spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01038     }
01039   }
01040 
01041   // Man kann Verteidiger haben. Diese kommen als erste zum Zuge
01042   if ( res=QueryProp(P_DEFENDERS) )
01043   { object *defs,*defs_here;
01044 
01045     defs=({});
01046     defs_here=({});
01047     if ( !pointerp(res) )
01048       res=({res});
01049     // erst alle anwesenden finden.
01050     foreach(object defender: res) {
01051       if ( objectp(defender) && (member(defs,defender)<0) )
01052       {
01053         defs+=({defender});
01054                 //  Verteidiger muessen im gleichen Raum oder im Living selber
01055                 //  enthalten sein.
01056         if ( environment(defender) == environment()
01057                     || environment(defender) == ME)
01058         {
01059           call_other(defender,"InformDefend",enemy);
01060           defs_here += ({ defender });
01061         }
01062       }
01063     }
01064     //Anwesende Verteidiger eintragen.
01065     spell[EINFO_DEFEND][PRESENT_DEFENDERS]=defs_here;
01066 
01067     // P_DEFENDERS auch gleich aktualisieren
01068     if ( sizeof(defs)<1 )
01069       defs=0;
01070     SetProp(P_DEFENDERS,defs);
01071 
01072     if ( spell[SP_PHYSICAL_ATTACK] ) {
01073       // Bei physischen Angriffen nur Verteidiger aus Reihe 1
01074       // nehmen (z.B. fuer Rueckendeckung)
01075       foreach(object defender: defs_here) {
01076         if ( (defender->PresentPosition())>1 ) {
01077           defs_here-=({defender});
01078         }
01079       }
01080     }
01081  
01082     if ( (i=sizeof(defs_here)) )
01083     {
01084       mixed edefendtmp=({defs_here[random(i)],0,0,0}); 
01085       res=call_other(edefendtmp[DEF_DEFENDER],"DefendOther",
01086                      dam,dam_type,spell,enemy);
01087       if ( pointerp(res) && (sizeof(res)>=3) && intp(res[0])
01088           && pointerp(res[1]))
01089       {
01090         // Helfer koennen den Schaden oder Schadenstyp aendern,
01091         // z.B. Umwandlung von Feuer nach Eis oder so...
01092         dam=res[0];
01093         edefendtmp[DEF_DAM]=dam;
01094         dam_type=res[1];
01095         edefendtmp[DEF_DAMTYPE]=dam_type;
01096 
01097         if ( mappingp(res[2]) )
01098         {
01099           spell=res[2];
01100                   // teuer, aber geht nicht anders (Rekursion vermeiden)
01101           edefendtmp[DEF_SPELL]=deep_copy(res[2]);
01102         }
01103         spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
01104         spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01105       }
01106       spell[EINFO_DEFEND][DEFENDING_DEFENDER]=edefendtmp;
01107     }
01108   } // Ende Defender-Verarbeitung
01109 
01110 
01111   // Ueber einen P_TMP_DEFEND_HOOK werden z.B. Schutzzauber gehandhabt
01112   spell[EINFO_DEFEND][DEFEND_HOOK]=DI_NOHOOK;
01113   if ( res=QueryProp(P_TMP_DEFEND_HOOK) )
01114   {
01115     if ( pointerp(res) && (sizeof(res)>=3) && intp(res[0]) && (time()<res[0])
01116         && objectp(res[1]) && stringp(res[2]) )
01117     {
01118       if ( !(res=call_other(res[1],res[2],dam,dam_type,spell,enemy)) )
01119       {
01120         // Ein P_TMP_DEFEND_HOOK kann den Schaden vollstaendig abfangen,
01121         // das Defend wird dann hier abgebrochen *SICK* und es wird nur
01122         // noch getestet, ob man in die Flucht geschlagen wurde
01123                 spell[EINFO_DEFEND][DEFEND_HOOK]=DI_HOOKINTERRUPT;
01124         CheckWimpyAndFlee();
01125                 return 0;
01126       }
01127       else
01128       {
01129                 spell[EINFO_DEFEND][DEFEND_HOOK]=DI_HOOK;
01130         if ( pointerp(res) && (sizeof(res)>=3)
01131             && intp(res[0] && pointerp(res[1])) )
01132         {
01133           mixed edefendtmp=({0,0,0});
01134           // Der P_TMP_DEFEND_HOOK kann ebenfalls Schadenshoehe und
01135           // -art sowie die Spell-Infos veraendern
01136           dam=res[0];
01137           edefendtmp[HOOK_DAM]=dam;
01138           dam_type=res[1];
01139           edefendtmp[HOOK_DAMTYPE]=dam_type;
01140 
01141           if ( mappingp(res[2]) )
01142           {
01143             spell=res[2];
01144                     // Waeh. Teuer. Aber geht nicht anders.
01145             edefendtmp[HOOK_SPELL]=deep_copy(spell);
01146           }
01147           spell[EINFO_DEFEND][DEFEND_HOOK]=edefendtmp;
01148           spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
01149           spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01150         }
01151       }
01152     }
01153     else
01154       SetProp(P_TMP_DEFEND_HOOK,0);
01155   } // P_TMP_DEFEND_HOOK
01156 
01157   // trigger defend hook
01158   hookData=({dam,dam_type,spell,enemy});
01159   hookRes=HookFlow(H_HOOK_DEFEND,hookData);
01160   if(hookRes && pointerp(hookRes) && sizeof(hookRes)>H_RETDATA){
01161     if(hookRes[H_RETCODE]==H_CANCELLED){
01162                 spell[EINFO_DEFEND][DEFEND_HOOK]=DI_HOOKINTERRUPT;
01163         CheckWimpyAndFlee();
01164                 return 0;
01165     }
01166     else if(hookRes[H_RETCODE]==H_ALTERED && hookRes[H_RETDATA]){
01167                 spell[EINFO_DEFEND][DEFEND_HOOK]=DI_HOOK;
01168         if ( pointerp(hookRes[H_RETDATA]) && (sizeof(hookRes[H_RETDATA])>=3)
01169             && intp(hookRes[H_RETDATA][0] && pointerp(hookRes[H_RETDATA][1])) )
01170         {
01171           mixed edefendtmp=({0,0,0});
01172           // Der P_TMP_DEFEND_HOOK kann ebenfalls Schadenshoehe und
01173           // -art sowie die Spell-Infos veraendern
01174           dam=hookRes[H_RETDATA][0];
01175           edefendtmp[HOOK_DAM]=dam;
01176           dam_type=hookRes[H_RETDATA][1];
01177           edefendtmp[HOOK_DAMTYPE]=dam_type;
01178 
01179           if ( mappingp(hookRes[H_RETDATA][2]) )
01180           {
01181             spell=hookRes[H_RETDATA][2];
01182                     // Teuer, teuer... :-(
01183             edefendtmp[HOOK_SPELL]=deep_copy(spell);
01184           }
01185           spell[EINFO_DEFEND][DEFEND_HOOK]=edefendtmp;
01186           spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
01187           spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01188         }
01189     }
01190   } // Ende Hook-Behandlung
01191 
01192   if ( !member(spell,SP_REDUCE_ARMOUR) || !mappingp(spell[SP_REDUCE_ARMOUR]) )
01193         spell[SP_REDUCE_ARMOUR] = ([]);
01194 
01195   // Es gibt auch Parierwaffen,
01196   if ( objectp(tmp=QueryProp(P_PARRY_WEAPON)) )
01197   {
01198     res2=tmp->QueryDefend(dam_type, spell, enemy);
01199 
01200     // Reduzierbare Wirksamkeit der Parierwaffe?
01201     if ( member(spell[SP_REDUCE_ARMOUR],P_PARRY_WEAPON)
01202         && intp(res=spell[SP_REDUCE_ARMOUR][P_PARRY_WEAPON]) && (res>=0) )
01203     {
01204       res2=(res2*res)/100;
01205     }
01206 
01207     dam-=res2;
01208     spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01209   }
01210 
01211   // Jetzt kommen die Ruestungen des Lebewesens ins Spiel (wenn es denn
01212   // welche traegt)
01213 
01214   armours=QueryProp(P_ARMOURS)-({0});
01215   if ( (i=sizeof(armours))>0 ) { 
01216     string aty;
01217 
01218     tmp=armours[random(i)];
01219 
01220     if ( objectp(tmp) )
01221       //Uebergabe des Mappings eh als Pointer/Referenz, daher billig
01222       tmp->TakeFlaw(dam_type,spell[EINFO_DEFEND]);
01223 
01224     // pro Ruestung ein Key an Platz reservieren
01225     spell[EINFO_DEFEND][DEFEND_ARMOURS]=m_allocate(i,2);
01226     foreach(object armour : armours) {
01227       if ( objectp(armour) ) {
01228         aty=(string)armour->QueryProp(P_ARMOUR_TYPE);
01229 
01230                 if ( member(spell[SP_REDUCE_ARMOUR],aty)
01231             && intp(res2=spell[SP_REDUCE_ARMOUR][aty]) && (res2>=0) )
01232           dam -= (res2*armour->QueryDefend(dam_type, spell, enemy))/100;
01233         else
01234           dam -= (int)(armour->QueryDefend(dam_type, spell, enemy));
01235                 // Schaden NACH DefendFunc vermerken. 
01236                 // Schutzwirkung VOR DefendFunc (DEF_ARMOUR_PROT) vermerkt
01237                 // das QueryDefend() selber.
01238                 spell[EINFO_DEFEND][DEFEND_ARMOURS][armour,DEF_ARMOUR_DAM]=dam;
01239         // akt. Schaden vermerken und Schutz der aktuellen Ruestung (vor
01240                 // DefendFunc) wieder auf 0 setzen fuer den naechsten Durchlauf.
01241         spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01242         spell[EINFO_DEFEND][DEFEND_CUR_ARMOUR_PROT]=0;
01243       }
01244     }
01245   }
01246 
01247   // Manche Gilden haben einen Verteidigungsskill. Der kommt jetzt zum
01248   // tragen. Der Skill kann die Schadenshoehe und -art beeinflussen.
01249   spell[EINFO_DEFEND]+=([DEFEND_GUILD:({})]);
01250   if ( mappingp(res=UseSkill(SK_MAGIC_DEFENSE,
01251                             ([ SI_ENEMY            : enemy,
01252                                SI_SKILLDAMAGE      : dam,
01253                                SI_SKILLDAMAGE_TYPE : dam_type,
01254                                SI_SPELL            : spell     ]))) )
01255   {
01256     dam=(int)res[SI_SKILLDAMAGE];
01257 
01258     if ( pointerp(res[SI_SKILLDAMAGE_TYPE]) )
01259         dam_type=res[SI_SKILLDAMAGE_TYPE];
01260 
01261     spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
01262     spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01263     spell[EINFO_DEFEND][DEFEND_GUILD]=({dam,dam_type});
01264   }
01265 
01266   // Evtl. interne Modifikationen
01267   InternalModifyDefend(&dam, &dam_type, &spell, &enemy);
01268 
01269   spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
01270   spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01271 
01272   // Testen, ob irgendwas im Inventory des Lebewesen auf den Angriff
01273   // "reagiert"
01274   CheckSensitiveAttack(dam,dam_type,spell,enemy);
01275 
01276   if ( !objectp(enemy) )
01277     return 0;
01278 
01279   // Angriffszeit im Gegner setzen
01280   enemy->SetProp(P_LAST_COMBAT_TIME,time());
01281 
01282   // Die Resistenzen des Lebewesens (natuerliche und durch Ruestungen
01283   // gesetzte) beruecksichtigen
01284   dam = (int)(CheckResistance(dam_type)*dam);
01285   spell[EINFO_DEFEND][DEFEND_RESI]=dam;
01286 
01287   spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01288 
01289   // Bei physikalischen Angriffen wird die natuerliche Panzerung und die
01290   // Geschicklichkeit des Lebewesens beruecksichtigt
01291   if ( spell[SP_PHYSICAL_ATTACK] )
01292   {
01293     res2=random(QueryProp(P_BODY)+QueryAttribute(A_DEX)+1);
01294 
01295     // Reduzierbare Wirksamkeit des Bodies?
01296     if ( member(spell[SP_REDUCE_ARMOUR], P_BODY)
01297         && intp(res=spell[SP_REDUCE_ARMOUR][P_BODY]) && (res>=0) )
01298       res2=(res2*res)/100;
01299 
01300     dam-=res2;
01301   }
01302   spell[EINFO_DEFEND][DEFEND_BODY]=dam;
01303   spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01304 
01305   // Ist ueberhaupt noch etwas vom Schaden uebrig geblieben?
01306   if ( dam<0 )
01307     dam = 0;
01308   spell[EINFO_DEFEND][CURRENT_DAM]=dam;
01309 
01310   // Die Anzahl der abzuziehenden Lebenspunkte ist der durch 10 geteilte
01311   // Schadenswert
01312   dam = dam / 10;
01313   spell[EINFO_DEFEND][DEFEND_LOSTLP]=dam;
01314 
01315 
01316   // In den meisten Faellen soll auch eine Schadensmeldung ausgegeben
01317   // werden, die die Hoehe des Schadens (grob) anzeigt
01318   if (spell[SP_SHOW_DAMAGE] && !pointerp(spell[SP_SHOW_DAMAGE])) {
01319     myname=name(WEN);
01320     enname=enemy->Name(WER);
01321     if (enemy->QueryProp(P_PLURAL)) {
01322       switch (dam) {
01323       case 0:
01324                 tell_object(enemy,sprintf("  Ihr verfehlt %s.\n",myname));
01325                 tell_object(this_object(),sprintf("  %s verfehlen Dich.\n",enname));
01326                 tell_room(environment(enemy)||environment(this_object()),
01327                   sprintf("  %s verfehlen %s.\n",enname,myname),
01328                           ({ enemy, this_object() }));
01329                 break;
01330       case 1:
01331                 tell_object(enemy,sprintf("  Ihr kitzelt %s am Bauch.\n",myname));
01332                 tell_object(this_object(),
01333                   sprintf("  %s kitzeln Dich am Bauch.\n",enname));
01334                 tell_room(environment(enemy)||environment(this_object()),
01335                   sprintf("  %s kitzeln %s am Bauch.\n",enname,myname),
01336                                   ({ enemy, this_object() }));
01337                 break;
01338       case 2..3:
01339                 tell_object(enemy,sprintf("  Ihr kratzt %s.\n",myname));
01340                 tell_object(this_object(),sprintf("  %s kratzen Dich.\n",enname));
01341                 tell_room(environment(enemy)||environment(this_object()),
01342                   sprintf("  %s kratzen %s.\n",enname,myname),
01343                                   ({ enemy, this_object() }));
01344                 break;
01345       case 4..5:
01346                 tell_object(enemy,sprintf("  Ihr trefft %s.\n",myname));
01347                 tell_object(this_object(),sprintf("  %s treffen Dich.\n",enname));
01348                 tell_room(environment(enemy)||environment(this_object()),
01349                   sprintf("  %s treffen %s.\n",enname,myname),
01350                                   ({ enemy, this_object() }));
01351                 break;
01352       case 6..10:
01353                 tell_object(enemy,sprintf("  Ihr trefft %s hart.\n",myname));
01354                 tell_object(this_object(),sprintf("  %s treffen Dich hart.\n",enname));
01355                 tell_room(environment(enemy)||environment(this_object()),
01356                   sprintf("  %s treffen %s hart.\n",enname,myname),
01357                                   ({ enemy, this_object() }));
01358                 break;
01359       case 11..20:
01360                 tell_object(enemy,sprintf("  Ihr trefft %s sehr hart.\n",myname));
01361                 tell_object(this_object(),
01362                   sprintf("  %s treffen Dich sehr hart.\n",enname));
01363                 tell_room(environment(enemy)||environment(this_object()),
01364                   sprintf("  %s treffen %s sehr hart.\n",enname,myname),
01365                                   ({ enemy, this_object() }));
01366                 break;
01367       case 21..30:
01368                 tell_object(enemy,
01369                   sprintf("  Ihr schlagt %s mit dem Krachen brechender Knochen.\n",
01370                                   myname));
01371                 tell_object(this_object(),
01372                   sprintf("  %s schlagen Dich mit dem Krachen brechender Knochen.\n",
01373                                   enname));
01374                 tell_room(environment(enemy)||environment(this_object()),
01375                   sprintf("  %s schlagen %s mit dem Krachen brechender Knochen.\n",
01376                                   enname,myname), ({ enemy, this_object() }));
01377                 break;
01378       case 31..50:
01379                 tell_object(enemy,
01380                   sprintf("  Ihr zerschmettert %s in kleine Stueckchen.\n",myname));
01381                 tell_object(this_object(),
01382                   sprintf("  %s zerschmettern Dich in kleine Stueckchen.\n",
01383                                                                                   enname));
01384                 tell_room(environment(enemy)||environment(this_object()),
01385                   sprintf("  %s zerschmettern %s in kleine Stueckchen.\n",
01386                                   enname,myname), ({ enemy, this_object() }));
01387                 break;
01388       case 51..75:
01389                 tell_object(enemy,sprintf("  Ihr schlagt %s zu Brei.\n",myname));
01390                 tell_object(this_object(),
01391                   sprintf("  %s schlagen Dich zu Brei.\n",enname));
01392                 tell_room(environment(enemy)||environment(this_object()),
01393                   sprintf("  %s schlagen %s zu Brei.\n",enname,myname),
01394                                   ({ enemy, this_object() }));
01395                 break;
01396       case 76..100:
01397                 tell_object(enemy,sprintf("  Ihr pulverisiert %s.\n",myname));
01398                 tell_object(this_object(),sprintf("  %s pulverisieren Dich.\n",enname));
01399                 tell_room(environment(enemy)||environment(this_object()),
01400                   sprintf("  %s pulverisieren %s.\n",enname,myname),
01401                                   ({ enemy, this_object() }));
01402                 break;
01403       case 101..150:
01404                 tell_object(enemy,sprintf("  Ihr zerstaeubt %s.\n",myname));
01405                 tell_object(this_object(),sprintf("  %s zerstaeuben Dich.\n",enname));
01406                 tell_room(environment(enemy)||environment(this_object()),
01407                   sprintf("  %s zerstaeuben %s.\n",enname,myname),
01408                                   ({ enemy, this_object() }));
01409                 break;
01410       case 151..200:
01411                 tell_object(enemy,sprintf("  Ihr atomisiert %s.\n",myname));
01412                 tell_object(this_object(),sprintf("  %s atomisieren Dich.\n",enname));
01413                 tell_room(environment(enemy)||environment(this_object()),
01414                   sprintf("  %s atomisieren %s.\n",enname,myname),
01415                                   ({ enemy, this_object() }));
01416                 break;
01417       default:
01418                 tell_object(enemy,sprintf("  Ihr vernichtet %s.\n",myname));
01419                 tell_object(this_object(),sprintf("  %s vernichten Dich.\n",enname));
01420                 tell_room(environment(enemy)||environment(this_object()),
01421                   sprintf("  %s vernichten %s.\n",enname,myname),
01422                                   ({ enemy, this_object() }));
01423                 break;
01424       }
01425 
01426     }
01427     else {
01428       switch (dam) {
01429       case 0:
01430                 tell_object(enemy,sprintf("  Du verfehlst %s.\n",myname));
01431                 tell_object(this_object(),sprintf("  %s verfehlt Dich.\n",enname));
01432                 tell_room(environment(enemy)||environment(this_object()),
01433                   sprintf("  %s verfehlt %s.\n",enname,myname),
01434                                   ({ enemy, this_object() }));
01435                 break;
01436       case 1:
01437                 tell_object(enemy,sprintf("  Du kitzelst %s am Bauch.\n",myname));
01438                 tell_object(this_object(),
01439                   sprintf("  %s kitzelt Dich am Bauch.\n",enname));
01440                 tell_room(environment(enemy)||environment(this_object()),
01441                   sprintf("  %s kitzelt %s am Bauch.\n",enname,myname),
01442                                   ({ enemy, this_object() }));
01443                 break;
01444       case 2..3:
01445                 tell_object(enemy,sprintf("  Du kratzt %s.\n",myname));
01446                 tell_object(this_object(),sprintf("  %s kratzt Dich.\n",enname));
01447                 tell_room(environment(enemy)||environment(this_object()),
01448                   sprintf("  %s kratzt %s.\n",enname,myname),
01449                                   ({ enemy, this_object() }));
01450                 break;
01451       case 4..5:
01452                 tell_object(enemy,sprintf("  Du triffst %s.\n",myname));
01453                 tell_object(this_object(),sprintf("  %s trifft Dich.\n",enname));
01454                 tell_room(environment(enemy)||environment(this_object()),
01455                   sprintf("  %s trifft %s.\n",enname,myname),
01456                                   ({ enemy, this_object() }));
01457                 break;
01458       case 6..10:
01459                 tell_object(enemy,sprintf("  Du triffst %s hart.\n",myname));
01460                 tell_object(this_object(),sprintf("  %s trifft Dich hart.\n",enname));
01461                 tell_room(environment(enemy)||environment(this_object()),
01462                   sprintf("  %s trifft %s hart.\n",enname,myname),
01463                     ({ enemy, this_object() }));
01464                 break;
01465       case 11..20:
01466                 tell_object(enemy,sprintf("  Du triffst %s sehr hart.\n",myname));
01467                 tell_object(this_object(),
01468                   sprintf("  %s trifft Dich sehr hart.\n",enname));
01469                 tell_room(environment(enemy)||environment(this_object()),
01470                   sprintf("  %s trifft %s sehr hart.\n",enname,myname),
01471                                   ({ enemy, this_object() }));
01472                 break;
01473       case 21..30:
01474                 tell_object(enemy,
01475                   sprintf("  Du schlaegst %s mit dem Krachen brechender Knochen.\n",
01476                                   myname));
01477                 tell_object(this_object(),
01478                   sprintf("  %s schlaegt Dich mit dem Krachen brechender Knochen.\n",
01479                                   enname));
01480                 tell_room(environment(enemy)||environment(this_object()),
01481                   sprintf("  %s schlaegt %s mit dem Krachen brechender Knochen.\n",
01482                                   enname,myname), ({ enemy, this_object() }));
01483                 break;
01484       case 31..50:
01485                 tell_object(enemy,
01486                   sprintf("  Du zerschmetterst %s in kleine Stueckchen.\n",myname));
01487                 tell_object(this_object(),
01488                   sprintf("  %s zerschmettert Dich in kleine Stueckchen.\n",enname));
01489                 tell_room(environment(enemy)||environment(this_object()),
01490                   sprintf("  %s zerschmettert %s in kleine Stueckchen.\n",
01491                                   enname,myname), ({ enemy, this_object() }));
01492                 break;
01493       case 51..75:
01494                 tell_object(enemy,sprintf("  Du schlaegst %s zu Brei.\n",myname));
01495                 tell_object(this_object(),
01496                   sprintf("  %s schlaegt Dich zu Brei.\n",enname));
01497                 tell_room(environment(enemy)||environment(this_object()),
01498                   sprintf("  %s schlaegt %s zu Brei.\n",enname,myname),
01499                                   ({ enemy, this_object() }));
01500                 break;
01501       case 76..100:
01502                 tell_object(enemy,sprintf("  Du pulverisierst %s.\n",myname));
01503                 tell_object(this_object(),sprintf("  %s pulverisiert Dich.\n",enname));
01504                 tell_room(environment(enemy)||environment(this_object()),
01505                   sprintf("  %s pulverisiert %s.\n",enname,myname),
01506                           ({ enemy, this_object() }));
01507                 break;
01508       case 101..150:
01509                 tell_object(enemy,sprintf("  Du zerstaeubst %s.\n",myname));
01510                 tell_object(this_object(),sprintf("  %s zerstaeubt Dich.\n",enname));
01511                 tell_room(environment(enemy)||environment(this_object()),
01512                   sprintf("  %s zerstaeubt %s.\n",enname,myname),
01513                                   ({ enemy, this_object() }));
01514                 break;
01515       case 151..200:
01516                 tell_object(enemy,sprintf("  Du atomisierst %s.\n",myname));
01517                 tell_object(this_object(),sprintf("  %s atomisiert Dich.\n",enname));
01518                 tell_room(environment(enemy)||environment(this_object()),
01519                   sprintf("  %s atomisiert %s.\n",enname,myname),
01520                                   ({ enemy, this_object() }));
01521                 break;
01522       default:
01523                 tell_object(enemy,sprintf("  Du vernichtest %s.\n",myname));
01524                 tell_object(this_object(),sprintf("  %s vernichtet Dich.\n",enname));
01525                 tell_room(environment(enemy)||environment(this_object()),
01526                   sprintf("  %s vernichtet %s.\n",enname,myname),
01527                                   ({ enemy, this_object() }));
01528                 break;
01529       }
01530     }
01531   }
01532 
01533   // Man kann auch selbst-definierte Schadensmeldungen ausgeben lassen
01534   else if( (res=spell[SP_SHOW_DAMAGE]) && pointerp(res) )
01535   {
01536     for( i=sizeof(res)-1 ; i-- ; )
01537     {
01538       if ( dam>res[i][0] )
01539       {
01540         tell_object(ME,mess(res[i][1],ME,enemy));
01541         tell_object(enemy,mess(res[i][2],ME,enemy));
01542         say(mess(res[i][3],ME,enemy), enemy);
01543         break;
01544       }
01545     }
01546   }
01547   // else keine Schadensmeldung.
01548 
01549   // Informationen ueber den letzten Angriff festhalten
01550   Set(P_LAST_DAMTYPES, dam_type);
01551   Set(P_LAST_DAMTIME,  time());
01552   Set(P_LAST_DAMAGE,   dam);
01553 
01554   // Bei Angriffen mit SP_NO_ENEMY-Flag kann man nicht sterben ...
01555   if ( spell[SP_NO_ENEMY] )
01556     reduce_hit_points(dam);
01557   // ... bei allen anderen natuerlich schon
01558   else
01559     do_damage(dam,enemy);
01560 
01561   // evtl. ist dies Objekt hier tot...
01562   if (!objectp(ME)) return dam;
01563 
01564   // Testen, ob man in die Fucht geschlagen wird
01565   CheckWimpyAndFlee();
01566 
01567   // Verursachten Schaden (in LP) zurueckgeben
01568   return dam;
01569 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public mixed DefendOther ( int  dam,
mixed  dam_type,
mixed  spell,
object  enemy 
)

Definiert in Zeile 919 der Datei combat.c.

Benutzt SI_ENEMY, SI_FRIEND, SI_SKILLDAMAGE, SI_SKILLDAMAGE_TYPE, SI_SPELL, SK_DEFEND_OTHER und UseSkill().

00920 { mixed res;
00921 
00922   if ( (res=UseSkill(SK_DEFEND_OTHER,([ SI_SKILLDAMAGE : dam,
00923                                         SI_SKILLDAMAGE_TYPE : dam_type,
00924                                         SI_SPELL : spell,
00925                                         SI_FRIEND : previous_object(),
00926                                         SI_ENEMY : enemy ])))
00927       && pointerp(res) )
00928     return res;
00929 
00930   return 0;
00931 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public mixed EnemyPresent (  ) 

Definiert in Zeile 1726 der Datei combat.c.

Benutzt enemies.

Wird benutzt von Flee() und InFight().

01727 {
01728   foreach(object en: enemies) {
01729     if (environment()==environment(en))
01730       return en;
01731   }
01732   return 0;
01733 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public varargs void ExecuteMissingAttacks ( object *  remove_attackers  ) 

Definiert in Zeile 2006 der Datei combat.c.

Benutzt ME, missing_attacks und ob().

Wird benutzt von ExitAttack() und InitAttack().

02007 {
02008   if ( !pointerp(missing_attacks) )
02009     missing_attacks=({});
02010 
02011   if ( pointerp(remove_attackers) )
02012     missing_attacks-=remove_attackers;
02013 
02014   foreach(object ob : missing_attacks) {
02015     if ( objectp(ob) && (environment(ob)==environment()) )
02016       ob->Attack2(ME);
02017   }
02018   missing_attacks=({});
02019 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public void ExitAttack (  ) 

Definiert in Zeile 2070 der Datei combat.c.

Benutzt ExecuteMissingAttacks() und ME.

Wird benutzt von move().

02071 {
02072   if ( !living(ME) )
02073     return;
02074 
02075   // Noch nachzuholende Begruessungsschlaege:
02076   ExecuteMissingAttacks();
02077 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

varargs public void ExtraAttack ( object  enemy,
int  ignore_previous 
)

Definiert in Zeile 626 der Datei combat.c.

Benutzt Attack() und no_more_attacks.

00627 {
00628   int saved_no_more_attacks;
00629 
00630   // Erstschlagsinfo speichern.
00631   saved_no_more_attacks = no_more_attacks;
00632 
00633   // Bei Bedarf bisher schon durchgefuehrte Erstschlaege ignorieren
00634   if (ignore_previous) no_more_attacks=0;
00635 
00636   // Normalen Angriff durchfuehren
00637   Attack (enemy);
00638 
00639   // Gespeicherten Wert zuruecksetzen
00640   no_more_attacks = saved_no_more_attacks;
00641 
00642   return;
00643 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public varargs void Flee ( object  oldenv,
int  force 
)

Definiert in Zeile 1654 der Datei combat.c.

Benutzt command, EnemyPresent(), env(), exit, exits, i, IS_LEARNER, IS_LEARNING, IS_SEER, ME, P_EXITS, P_GHOST, P_HP, P_LEVEL, P_SPECIAL_EXITS, P_WIMPY, P_WIMPY_DIRECTION, QueryProp() und TeamFlee().

Wird benutzt von heart_beat().

01655 { mixed   *exits, exit, dex;
01656   mapping tmp;
01657   int     i;
01658   object  env;
01659 
01660   if ( !environment() )
01661     return;
01662 
01663   // mit 'force' kann man die Checks umgehen, damit der Spieler auf jeden
01664   // Fall fluechtet ...
01665   if ( !force && ( oldenv && (oldenv != environment()) ||
01666                    query_once_interactive(ME) && (!EnemyPresent() ||
01667                    (QueryProp(P_HP) >= QueryProp(P_WIMPY))) ) )
01668     return;
01669 
01670   // ... aber Magier fluechten zu lassen ist nicht ganz so einfach ;-)
01671   if ( query_once_interactive(this_object()) && IS_LEARNING(this_object()) )
01672     return;
01673 
01674   // Geister brauchen nicht um ihr Leben zu fuerchten
01675   if ( QueryProp(P_GHOST) )
01676     return;
01677 
01678   tell_object( ME, "Die Angst ist staerker als Du ... "+
01679                    "Du willst nur noch weg hier.\n");
01680 
01681   if ( TeamFlee() ) // Erfolgreiche Flucht in hintere Kampfreihe?
01682     return;
01683 
01684   env = environment();
01685   tmp = environment()->QueryProp(P_EXITS);
01686   exits = m_indices(tmp);
01687   tmp = environment()->QueryProp(P_SPECIAL_EXITS);
01688   exits += m_indices(tmp);
01689 
01690   if ( query_once_interactive(ME) )
01691                 exits = map( exits, #'_kill_alias/*'*/ );
01692 
01693   // die Fluchtrichtung von Magiern wird aus Sicherheitsgruenden
01694   // nicht ausgewertet
01695   if ( interactive(ME) && IS_SEER(ME) && !IS_LEARNER(ME)
01696       && (dex=QueryProp(P_WIMPY_DIRECTION)) )
01697   {
01698     i = 60 + 4 * (QueryProp(P_LEVEL) - 30) / 3;
01699     exits += ({dex}); // bevorzugte Fluchtrichtung mindestens einmal
01700   }
01701 
01702   if ( !sizeof(exits) )
01703   {
01704     tell_object( ME, "Du versuchst zu fliehen, schaffst es aber nicht.\n" );
01705 
01706     return;
01707   }
01708 
01709   while ( sizeof(exits) && (environment()==env) )
01710   {
01711     if ( dex                         // Vorzugsweise Fluchtrichtung?
01712         && (member(exits,dex) >= 0)  // moeglich?
01713         && (random(100) <= i))       // und Wahrscheinlichkeit gross genug?
01714       exit = dex;
01715     else
01716       exit = exits[random(sizeof(exits))];
01717 
01718     catch(command(exit);publish);
01719     exits -= ({exit});
01720   }
01721 
01722   if ( environment()==env )
01723     tell_object( ME, "Dein Fluchtversuch ist gescheitert.\n" );
01724 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public varargs int FreeHands ( object  ob  ) 

Definiert in Zeile 1963 der Datei combat.c.

Benutzt P_HANDS_USED_BY, QueryProp() und SetProp().

Wird benutzt von _set_used_hands().

01964 {
01965   if ( !ob && !(ob=previous_object(1)) )
01966     return 0;
01967 
01968   SetProp(P_HANDS_USED_BY,QueryProp(P_HANDS_USED_BY)-({ob}));
01969 
01970   return 1;
01971 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public mapping GetEnemies (  ) 

Definiert in Zeile 1638 der Datei combat.c.

Benutzt enemies.

01639 {
01640   return enemies;
01641 }

protected void heart_beat (  ) 

Definiert in Zeile 376 der Datei combat.c.

Benutzt Attack(), attack_busy, enemies, Flee(), here(), HUNTTIME, i, IS_SEER, m_delete(), ME, netdead, no_attack(), no_more_attacks, P_DISABLE_ATTACK, P_GUILD_PREPAREBLOCK, P_HP, P_HUNTTIME, P_LEVEL, P_NO_ATTACK, P_PREPARED_SPELL, P_WIMPY, QueryProp(), QuerySkillAttribute(), remaining_heart_beats, SA_SPEED, SelectNearEnemy(), SetProp(), StopHuntFor() und UseSpell().

00376                             {
00377   int hbs; 
00378   // leider rufen viele Leute einfach das geerbte heart_beat() obwohl sie
00379   // schon tot sind und damit das Objekt zerstoert ist.
00380   if (!living(this_object()))
00381       return;
00382 
00383   // Paralyse pruefen, ggf. reduzieren
00384   int dis_attack = QueryProp(P_DISABLE_ATTACK);
00385   if ( intp(dis_attack) && (dis_attack > 0) ) {
00386       SetProp(P_DISABLE_ATTACK, --dis_attack);
00387   }
00388 
00389   // Attacken ermitteln: SA_SPEED + Rest aus dem letzten HB
00390   hbs = remaining_heart_beats + QuerySkillAttribute(SA_SPEED);
00391   if ( hbs <= 0 )
00392     hbs = 100; 
00393 
00394   // P_ATTACK_BUSY bestimmen
00395   if ( attack_busy > 99) 
00396    attack_busy = 100 + hbs;
00397   else
00398     attack_busy += 100 + hbs;
00399   // mehr fuer Seher...
00400   if ( IS_SEER(ME) )
00401     attack_busy+=(100+QueryProp(P_LEVEL)); 
00402   // max. 500, d.h. 5 Attacken
00403   if ( attack_busy>500 )
00404     attack_busy=500;
00405 
00406   // unganzzahligen Rest fuer naechsten HB speichern
00407   remaining_heart_beats = hbs % 100;
00408   hbs /= 100; // ganze Attacken. ;-)
00409 
00410   if ( hbs > 10 ) // nicht mehr als 10 Attacken.
00411     hbs = 10; 
00412 
00413   // Falls jemand seit dem letzten HB in diesem Living von aussen Attack()
00414   // gerufen hat (nicht ExtraAttack()), wird jetzt was abgezogen.
00415   hbs -= no_more_attacks;
00416   no_more_attacks = 0;
00417 
00418   // Wie lange verfolgt dieser NPC? Wenn Prop nicht gesetzt oder ungueltig,
00419   // d.h. kein int oder <= 0, dann wird die Defaultzeit genommen.
00420   int hunttime = (int)QueryProp(P_HUNTTIME);
00421   hunttime = (intp(hunttime) && hunttime > 0) ? 
00422               hunttime / __HEART_BEAT_INTERVAL__ : HUNTTIME;
00423   // erstmal die Hunttimes der Gegner aktualisieren und nebenbei die
00424   // anwesenden Feinde merken. Ausserdem ggf. Kampf abbrechen, wenn
00425   // P_NO_ATTACK gesetzt ist.
00426   // eigentlich ist diese ganze Schleife fast das gleiche wie
00427   // PresentEnemies(), aber leider muessen ja die Hunttimes aktulisiert werde,
00428   // daher kann man nicht direkt PresentEnemies() nehmen.
00429   // TODO: Diese Schleife und PresentEnmies() irgendwie vereinigen.
00430   object *netdead=({});
00431   object *here=({});
00432   object enemy;
00433   mixed no_attack;
00434   foreach(enemy, int htime: &enemies) { // Keys in enemy
00435     // ggf. Meldungen ausgeben und Gegner austragen und dieses Living beim
00436     // Gegner austragen.
00437     if (no_attack=enemy->QueryProp(P_NO_ATTACK)) {
00438       efun::m_delete(enemies,enemy);
00439         if ( stringp(no_attack) ) {
00440             write( no_attack );
00441             enemy->StopHuntFor( ME, 1 );
00442         }
00443         else
00444             enemy->StopHuntFor( ME, 0 );
00445     }
00446     else if ( environment()==environment(enemy) ) {
00447       // Gegner anwesend, als Feind merken...
00448       if ( interactive(enemy) || !query_once_interactive(enemy) )
00449         here+=({enemy});
00450       else
00451         netdead+=({enemy});
00452       // ... und Hunttime erneuern.
00453       htime = hunttime;
00454     }
00455     // Feind nicht anwesend. Timer dekrementieren und Feind austragen, wenn
00456     // Jagdzeit abgelaufen.
00457     else if ( (--htime) <= 0 )
00458       StopHuntFor(enemy);
00459   }
00460   // Netztote sind nur Feinde, wenn sonst keine da sind.
00461   if ( !sizeof(here) )
00462     here=netdead;
00463 
00464   // schonmal abfragen, ob ein Spell vorbereitet wird.
00465   mixed pspell=QueryProp(P_PREPARED_SPELL);
00466 
00467   //Da hbs 0 und no_more_attacks durch einen manuellen Aufruf von Attack() im
00468   //Spieler >0 sein kann, kann jetzt hbs <0 sein. (s.o.)
00469   if (hbs > 0 && sizeof(here)) {
00470     foreach(int i: hbs) {
00471       // Feind in Nahkampfreichweite finden
00472       if ( objectp(enemy=SelectNearEnemy(here)) ) {
00473                 // Flucht erwuenscht?
00474                 if ( QueryProp(P_WIMPY) > QueryProp(P_HP) ) {
00475                   Flee();
00476                   // Flucht gelungen?
00477                   if ( enemy && (environment(enemy)!=environment()) ) {
00478                     here = 0; // naechste Runde neue Feinde suchen
00479                     enemy = 0;
00480                     continue; // kein Kampf, Runde ueberspringen
00481                   }
00482                 }
00483       }
00484       else {
00485                 // keine Feinde gefunden... Abbrechen.
00486                 break;
00487       }
00488       // Paralyse gesetzt? -> Abbrechen. Dieses Pruefung muss hier passieren,
00489       // damit ggf. die automatische Flucht des Lebewesens durchgefuehrt wird,
00490       // auch wenn es paralysiert ist.
00491       if (dis_attack > 0) break;
00492 
00493       // Kampf durch Spell-Prepare blockiert?
00494       // Keine genaue Abfrage, wird spaeter noch genau geprueft.
00495       if ( pspell && QueryProp(P_GUILD_PREPAREBLOCK) )
00496                 break; // keine Angriffe in diesem HB.
00497       // wenn Feind da: hit'em hard.
00498       if ( objectp(enemy) )
00499                 Attack(enemy);
00500       // ggf. hat Attack() no_more_attacks gesetzt. Zuruecksetzen
00501       no_more_attacks = 0;
00502       // naechste Kampfrunde neue Feinde suchen
00503       here = 0;
00504     }  // foreach
00505   }
00506 
00507   no_more_attacks=0;
00508 
00509   // Ist ein Spell in Vorbereitung und evtl. jetzt fertig vorbereitet?
00510   if ( pointerp(pspell)
00511       && (sizeof(pspell)>=3) && intp(pspell[0]) && stringp(pspell[1]) ) {
00512     if ( time()>=pspell[0] ) // Kann der Spruch jetzt ausgefuehrt werden?
00513     {
00514       UseSpell(pspell[2],pspell[1]); // Dann los
00515       SetProp(P_PREPARED_SPELL,0);
00516     }
00517   }
00518   else if ( pspell ) // Unbrauchbarer Wert, loeschen
00519     SetProp(P_PREPARED_SPELL,0);
00520 
00521 } // Ende heart_beat

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public mixed InFight (  ) 

Definiert in Zeile 1735 der Datei combat.c.

Benutzt EnemyPresent().

Wird benutzt von _query_hb(), ConfigureColors(), heart_beat() und Walk().

01736 {
01737   return EnemyPresent();
01738 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public void InformDefend ( object  enemy  ) 

Definiert in Zeile 910 der Datei combat.c.

Benutzt SI_ENEMY, SI_FRIEND, SK_INFORM_DEFEND und UseSkill().

00911 {
00912   UseSkill(SK_INFORM_DEFEND,([ SI_ENEMY  : enemy,
00913                                SI_FRIEND : previous_object() ]));
00914   // Oh, oh - ich hoffe mal, dass InformDefend wirklich NUR aus Defend
00915   // eines befreundeten livings aufgerufen wird... (Silvana)
00916   // This is only experimental... ;)
00917 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public void InitAttack (  ) 

Definiert in Zeile 2021 der Datei combat.c.

Benutzt Attack2(), ExecuteMissingAttacks(), InsertEnemy(), IsEnemy(), IsTeamMove(), ME, missing_attacks, ob(), P_GHOST und QueryProp().

Wird benutzt von NotifyMove().

02022 { object ob,next;
02023   closure cb;
02024 
02025   if ( !living(ME) )
02026     return;
02027 
02028   ExecuteMissingAttacks();
02029   //EMA kann das Living zerstoeren oder toeten...
02030   if (!living(ME) || QueryProp(P_GHOST)) return;
02031 
02032   if ( objectp(ob=IsTeamMove()) )
02033     cb=symbol_function("InitAttack_Callback",ob);
02034   else
02035     cb=0;
02036 
02037   for ( ob=first_inventory(environment()) ; objectp(ob) ; ob=next)
02038   {
02039     next=next_inventory(ob);
02040 
02041     if ( !living(ob) )
02042       continue;
02043 
02044     if (ob->IsEnemy(ME))
02045     {
02046       // Das ist nicht so sinnlos wie es aussieht. a) werden die Hunttimes
02047       // aktualisiert und b) werden Teammitglieder von mir bei diesem
02048       // InsertEnemy() ggf. erfasst.
02049       ob->InsertEnemy(ME);
02050 
02051       if ( closurep(cb) && funcall(cb,ob) ) // Wird ganzes Team gemoved?
02052         missing_attacks += ({ ob }); // Dann erstmal warten bis alle da sind
02053       else
02054         ob->Attack2(ME);
02055 
02056     }
02057     else if ( IsEnemy(ob) )
02058     {
02059       // Das ist nicht so sinnlos wie es aussieht. a) werden die Hunttimes
02060       // aktualisiert und b) werden Teammitglieder von ob bei diesem 
02061       // InsertEnemy() ggf. erfasst.
02062       InsertEnemy(ob);
02063       Attack2(ob);
02064     }
02065     //Attack2 kann dieses Objekt zerstoeren oder toeten. Wenn ja: abbruch
02066     if ( !living(ME) || QueryProp(P_GHOST)) break;
02067   }
02068 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public int InsertEnemy ( object  ob  ) 

Definiert in Zeile 290 der Datei combat.c.

Benutzt InsertEnemyTeam() und InsertSingleEnemy().

00291 { int res;
00292 
00293   if ( res=InsertSingleEnemy(ob) )
00294     InsertEnemyTeam(ob);
00295 
00296   return res;
00297 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public int InsertSingleEnemy ( object  ob  ) 

Definiert in Zeile 249 der Datei combat.c.

Benutzt enemies, ENEMY_HUNTTIME, HUNTTIME, last_attack_msg, ME, P_GHOST, P_HUNTTIME, P_LAST_COMBAT_TIME, P_NO_ATTACK, P_TEAM, Query(), QueryProp(), Set() und team.

Wird benutzt von InsertEnemy() und InsertEnemyTeam().

00250 {
00251     if ( !living(ob) )
00252         return 1;
00253 
00254     // Wie lange verfolgt dieses Living? Wenn Prop nicht gesetzt oder 
00255     // ungueltig, d.h. kein int oder <= 0, dann wird die Defaultzeit genommen.
00256     int hunttime = (int)QueryProp(P_HUNTTIME);
00257     hunttime = (intp(hunttime) && hunttime > 0) ? 
00258                  hunttime / __HEART_BEAT_INTERVAL__ : HUNTTIME;
00259 
00260     // Auch wenn ein Objekt schon als Gegner eingetragen ist, trotzdem die
00261     // HUNTTIME erneuern. Das "return 0;" muss aber bleiben, da der Gegner
00262     // ja nicht neu ist.
00263     //
00264     // 09.12.2000, Tiamak
00265     if ( member( enemies, ob ) ) {
00266         enemies[ob,ENEMY_HUNTTIME] = hunttime;
00267         return 0;
00268     }
00269 
00270     if ( (ob==ME) || QueryProp(P_NO_ATTACK)
00271          || !objectp(ob) || (ob->QueryProp(P_NO_ATTACK))
00272          || (ob->QueryProp(P_GHOST)) )
00273         return 0;
00274 
00275     object team;
00276     if ( ( query_once_interactive(ME) || query_once_interactive(ob) )
00277          && objectp(team=Query(P_TEAM)) && (team==(ob->Query(P_TEAM))) )
00278         return 0;
00279 
00280     set_heart_beat(1);
00281 
00282     last_attack_msg=0;
00283 
00284     enemies[ob,ENEMY_HUNTTIME] = hunttime;
00285     Set(P_LAST_COMBAT_TIME,time());
00286 
00287     return 1;
00288 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

protected void InternalModifyAttack ( mapping  ainfo  ) 

Definiert in Zeile 602 der Datei combat.c.

Wird benutzt von Attack().

00603 {
00604   return; // Vorerst!
00605 /*
00606   int   fac;
00607   mixed res;
00608 
00609   fac=100;
00610 
00611   if (CannotSee(1))
00612     fac -= 50;
00613 
00614   // Weitere Mali?
00615 
00616   if (fac<100)
00617     ainfo[SI_SKILLDAMAGE] = ainfo[SI_SKILLDAMAGE]*fac/100;
00618   // Fertig
00619 */
00620 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

protected void InternalModifyDefend ( int  dam,
mixed  dt,
mapping  spell,
object  enemy 
)

Definiert in Zeile 970 der Datei combat.c.

00971 {
00972   return;
00973 }

public int IsEnemy ( object  wer  ) 

Definiert in Zeile 537 der Datei combat.c.

Benutzt enemies.

Wird benutzt von AssocMember(), CheckEnemy(), InitAttack(), Kill(), mnpc_init(), QueryPlAttacked(), QueryPreferedEnemy() und StopHuntFor().

00538 {
00539   return (member(enemies,wer));
00540 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public int Kill ( object  ob  ) 

kill - Kampf starten.

Fuegt ob der Feindesliste hinzu.

Definiert in Zeile 214 der Datei combat.c.

Benutzt InsertEnemy(), ME, no_attack(), P_GHOST, P_NO_ATTACK, QueryProp() und WER.

Wird benutzt von heart_beat(), init() und Kill().

00215 { int   res, arena;
00216   mixed no_attack;
00217 
00218   if ( !objectp(ob) )
00219     return 0;
00220 
00221   if ( ob->QueryProp(P_GHOST) )
00222   {
00223     tell_object(ME,ob->Name(WER)+" ist doch schon tot!\n");
00224     return -1;
00225   }
00226 
00227   if ( no_attack = ob->QueryProp(P_NO_ATTACK) )
00228   {
00229     if ( stringp(no_attack) )
00230       tell_object(ME, no_attack);
00231     else
00232       tell_object(ME, ob->Name(WER,1)+" laesst sich nicht angreifen!\n");
00233 
00234     return -2;
00235   }
00236 
00237   if ( QueryProp(P_NO_ATTACK) )
00238     return -3;
00239 
00240   res=InsertEnemy(ob);
00241   tell_object(ME,(res?"Ok.":"Jajaja, machst Du doch schon!")+"\n");
00242 
00243   if ( !res )
00244     return -4;
00245 
00246   return 1;
00247 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

protected string mess ( string  msg,
object  me,
object  enemy 
)

Definiert in Zeile 940 der Datei combat.c.

Wird benutzt von udp_query().

00941 { closure mname, ename;
00942   string  *parts,x;
00943   int     i;
00944 
00945   mname = symbol_function("name", me);
00946   ename = symbol_function("name", enemy);
00947 
00948   parts=regexplode(msg,"@WE[A-Z]*[12]");
00949   for ( i=sizeof(parts)-2 ; i>=1 ; i-=2 )
00950   {
00951     switch(parts[i])
00952     {
00953       case "@WER1":    parts[i]=funcall(mname,WER,1);    break;
00954       case "@WESSEN1": parts[i]=funcall(mname,WESSEN,1); break;
00955       case "@WEM1":    parts[i]=funcall(mname,WEM,1);    break;
00956       case "@WEN1":    parts[i]=funcall(mname,WEN,1);    break;
00957       case "@WER2":    parts[i]=funcall(ename,WER,1);    break;
00958       case "@WESSEN2": parts[i]=funcall(ename,WESSEN,1); break;
00959       case "@WEM2":    parts[i]=funcall(ename,WEM,1);    break;
00960       case "@WEN2":    parts[i]=funcall(ename,WEN,1);    break;
00961       default: ;
00962     }
00963   }
00964 
00965   return break_string(capitalize(implode(parts,"")),78,"  ",1);
00966 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public int Pacify ( object  caster  ) 

Pacify() dient zur Bestimmung, ob sich ein Lebewesen gerade befrieden lassen will.

Berechnet eine Wahrscheinlichkeit nach unten stehender Formel, welche die Intelligenz dieses Lebenwesens, die Intelligenz des Casters und die bisherige Anzahl erfolgreicher Befriedungsversuche dieser Gilde eingeht. Anschliessend wird aus der Wahrscheinlichkeit und random() bestimmt, ob dieser Versuch erfolgreich ist. Formel: w = (INT_CASTER + 10 - ANZ*4) / (INT_ME + 10) INT_CASTER: Caster-Intelligenz, INT_ME: Intelligenz dieses Livings ANZ: Anzahl erfolgreicher Befriedungsversuche

Annahme: INT_CASTER === 22, alle Wahrscheinlichkeiten * 100

INT_ME Erfolgswahrscheinlichkeiten je nach Anzahl erfolgreicher Versuche 1 2 3 4 5 6 7 8 0 280 240 200 160 120 80 40 0 2 233,33 200 166,67 133,33 100 66,67 33,33 0 4 200 171,43 142,86 114,29 85,71 57,14 28,57 0 6 175 150 125 100 75 50 25 0 8 155,56 133,33 111,11 88,89 66,67 44,44 22,22 0 10 140 120 100 80 60 40 20 0 12 127,27 109,09 90,91 72,73 54,55 36,36 18,18 0 14 116,67 100 83,33 66,67 50 33,33 16,67 0 16 107,69 92,31 76,92 61,54 46,15 30,77 15,38 0 18 100 85,71 71,43 57,14 42,86 28,57 14,29 0 20 93,33 80 66,67 53,33 40 26,67 13,33 0 22 87,5 75 62,5 50 37,5 25 12,5 0 24 82,35 70,59 58,82 47,06 35,29 23,53 11,76 0 26 77,78 66,67 55,56 44,44 33,33 22,22 11,11 0 28 73,68 63,16 52,63 42,11 31,58 21,05 10,53 0 30 70 60 50 40 30 20 10 0 32 66,67 57,14 47,62 38,1 28,57 19,05 9,52 0 34 63,64 54,55 45,45 36,36 27,27 18,18 9,09 0 35 62,22 53,33 44,44 35,56 26,67 17,78 8,89 0 36 60,87 52,17 43,48 34,78 26,09 17,39 8,7 0 38 58,33 50 41,67 33,33 25 16,67 8,33 0 40 56 48 40 32 24 16 8 0 42 53,85 46,15 38,46 30,77 23,08 15,38 7,69 0 44 51,85 44,44 37,04 29,63 22,22 14,81 7,41 0 46 50 42,86 35,71 28,57 21,43 14,29 7,14 0 48 48,28 41,38 34,48 27,59 20,69 13,79 6,9 0 50 46,67 40 33,33 26,67 20 13,33 6,67 0 52 45,16 38,71 32,26 25,81 19,35 12,9 6,45 0 54 43,75 37,5 31,25 25 18,75 12,5 6,25 0 56 42,42 36,36 30,3 24,24 18,18 12,12 6,06 0 58 41,18 35,29 29,41 23,53 17,65 11,76 5,88 0 60 40 34,29 28,57 22,86 17,14 11,43 5,71 0 62 38,89 33,33 27,78 22,22 16,67 11,11 5,56 0 64 37,84 32,43 27,03 21,62 16,22 10,81 5,41 0 66 36,84 31,58 26,32 21,05 15,79 10,53 5,26 0 68 35,9 30,77 25,64 20,51 15,38 10,26 5,13 0 70 35 30 25 20 15 10 5 0 72 34,15 29,27 24,39 19,51 14,63 9,76 4,88 0 74 33,33 28,57 23,81 19,05 14,29 9,52 4,76 0 76 32,56 27,91 23,26 18,6 13,95 9,3 4,65 0 78 31,82 27,27 22,73 18,18 13,64 9,09 4,55 0 80 31,11 26,67 22,22 17,78 13,33 8,89 4,44 0 82 30,43 26,09 21,74 17,39 13,04 8,7 4,35 0 84 29,79 25,53 21,28 17,02 12,77 8,51 4,26 0 86 29,17 25 20,83 16,67 12,5 8,33 4,17 0 88 28,57 24,49 20,41 16,33 12,24 8,16 4,08 0 90 28 24 20 16 12 8 4 0 92 27,45 23,53 19,61 15,69 11,76 7,84 3,92 0 94 26,92 23,08 19,23 15,38 11,54 7,69 3,85 0 96 26,42 22,64 18,87 15,09 11,32 7,55 3,77 0 98 25,93 22,22 18,52 14,81 11,11 7,41 3,7 0 100 25,45 21,82 18,18 14,55 10,91 7,27 3,64 0

Rückgabe:
1, falls Befrieden erlaubt ist, 0 sonst.
Parameter:
[in] caster Derjenige, der den Spruch ausfuehrt.
Achtung:
Wenn acify() 1 zurueckliefert, zaehlt dies als erfolgreicher Befriedungsversuch und in diesem Lebewesen wurde StopHuntingMode(1) aufgerufen.

Definiert in Zeile 2236 der Datei combat.c.

Benutzt _decay_peace_history(), A_INT, enemies, gilde, ME, P_ACCEPT_PEACE, P_GUILD, P_PEACE_HISTORY, QueryAttribute(), QueryProp(), SetProp(), StopHuntingMode() und TeamMembers().

02236                                  {
02237   
02238   // wenn das Viech keine Gegner hat, dann witzlos. ;-) Ohne Caster gehts auch
02239   // direkt raus.
02240   if (!mappingp(enemies) || !sizeof(enemies)
02241       || !objectp(caster)) {
02242     return 0;
02243   }
02244 
02245   // Wenn P_ACCEPT_PEACE gesetzt ist, altes Verhalten wiederspiegeln
02246   // -> der NPC ist einfach immer befriedbar. Gleiches gilt fuer den Caster
02247   // selber, der wird sich ja nicht gegen das eigene Befriede wehren. Und auch
02248   // im team wehrt man sich nicht gegen das Befriede eines Teamkollegen
02249   if (QueryProp(P_ACCEPT_PEACE)==1 || caster==ME
02250       || member(TeamMembers(), caster) > -1) {
02251     StopHuntingMode(1); // Caster/Gilde sollte eigene Meldung ausgeben
02252     return 1;
02253   }
02254 
02255   string gilde = caster->QueryProp(P_GUILD) || "ANY";
02256 
02257   // ggf. P_PEACE_HISTORY initialisieren
02258   mixed ph = (mixed)QueryProp(P_PEACE_HISTORY);
02259   if (!pointerp(ph))
02260     SetProp(P_PEACE_HISTORY, ph=({time(), ([]) }) );
02261   
02262   // ggf. die Zaehler reduzieren.
02263   if ( ph[0] + __RESET_TIME__ * 75/100 < time()) {
02264     _decay_peace_history(&ph);
02265   }
02266   
02267   float w = (caster->QueryAttribute(A_INT) + 10 - ph[1][gilde] * 4.0) / 
02268              (QueryAttribute(A_INT) + 10);
02269   // auf [0,1] begrenzen.
02270   if (w<0) w=0.0;
02271   else if (w>1) w=1.0;
02272   // w * n ist eine Zahl zwischen 0 und n, wenn w * n > random(n)+1,
02273   // darf befriedet werden. Da das Random fuer grosse Zahlen
02274   // besser verteilt ist, nehm ich n = __INT_MAX__ und vernachlaessige
02275   // ausserdem die +1 beim random().
02276   if (ceil(w * __INT_MAX__) > random(__INT_MAX__) ) {
02277     ph[1][gilde]++;
02278     StopHuntingMode(1);
02279     return 1;
02280   }
02281   // ein SetProp(P_PEACE_HISTORY) kann entfallen, da das Mapping direkt
02282   // geaendert wird. Sollte die Prop allerdings mal ne Querymethode haben,
02283   // welche eine Kopie davon liefert, muss das hier geaendert oder die
02284   // Prop per Query() abgefragt werden.
02285   return 0;
02286 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public object* PresentEnemies (  ) 

Definiert in Zeile 329 der Datei combat.c.

Benutzt enemies, here(), m_delete(), ME, netdead, no_attack(), P_NO_ATTACK und pl.

Wird benutzt von eval_enemies(), maximize_prop_filt(), minimize_prop_filt(), player_filt(), PresentEnemyRows(), SelectEnemy(), SelectFarEnemy() und SelectNearEnemy().

00329                                 {
00330 
00331   object *here=({});
00332   object *netdead=({});
00333   string no_attack;
00334   foreach(object pl: enemies) {
00335     if (no_attack = (mixed)pl->QueryProp(P_NO_ATTACK)) {
00336       efun::m_delete(enemies,pl);
00337       // Und auch im Gegner austragen, sonst haut der weiter zu und dieses
00338       // Living wehrt sich nicht. (Zesstra, 26.11.2006)
00339       if (stringp(no_attack)) {
00340                 tell_object(ME, no_attack);
00341                 pl->StopHuntFor(ME, 1);
00342       }
00343       else pl->StopHuntFor(ME, 0);
00344     }
00345     else if ( environment()==environment(pl) )
00346     {
00347       if ( interactive(pl) || !query_once_interactive(pl) )
00348         here+=({pl});
00349       else
00350         netdead+=({pl});
00351     }
00352   }
00353 
00354   if ( !sizeof(here) ) // Netztote sind nur Feinde, falls keine anderen da sind
00355     return netdead;
00356 
00357   return here;
00358 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public mixed QueryArmourByType ( string  type  ) 

Definiert in Zeile 2079 der Datei combat.c.

Benutzt armours, AT_MISC, ob(), P_ARMOUR_TYPE, P_ARMOURS, QABTCache und QueryProp().

02080 {
02081   // Rueckgabewert:
02082   // DIE Ruestung vom Typ <type>, falls <type> nicht AT_MISC,
02083   // Array aller AT_MISC-Ruestungen falls <type> AT_MISC (auch leer),
02084   // Mapping mit allen oben genannten Infos, falls <type> Null
02085 
02086   object *armours;
02087   string typ2;
02088 
02089   // Wenn Cache vorhanden, dann Cache liefern.
02090   if (mappingp(QABTCache)) {
02091     if (type == AT_MISC)
02092       return QABTCache[AT_MISC] - ({0});
02093     else if (type)
02094       return QABTCache[type];
02095     else
02096       return copy(QABTCache);
02097   }
02098 
02099   if ( !pointerp(armours=QueryProp(P_ARMOURS)) )
02100     armours=({});
02101 
02102   // Cache erzeugen
02103   QABTCache = ([ AT_MISC: ({}) ]);
02104   foreach(object ob: armours - ({0}) ) {
02105     if ( !stringp(typ2=ob->QueryProp(P_ARMOUR_TYPE)) )
02106       continue;
02107     if ( typ2==AT_MISC )
02108       QABTCache[AT_MISC] += ({ob});
02109     else
02110       QABTCache[typ2] = ob;
02111   }
02112   // Und gewuenschtes Datum liefern.
02113   if (type)
02114     return QABTCache[type];
02115   else
02116     return copy(QABTCache);
02117 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public mixed QueryEnemies (  ) 

Definiert in Zeile 1633 der Datei combat.c.

Benutzt enemies.

01634 {
01635   return ({m_indices(enemies),m_values(enemies)});
01636 }

public object QueryPreferedEnemy (  ) 

Definiert in Zeile 299 der Datei combat.c.

Benutzt IsEnemy(), P_PREFERED_ENEMY, QueryProp() und SetProp().

Wird benutzt von SelectEnemy().

00300 { int    sz,r;
00301   mixed  pref;
00302   object enemy;
00303 
00304   enemy=0;
00305   if ( pointerp(pref=QueryProp(P_PREFERED_ENEMY)) && ((sz=sizeof(pref))>1)
00306       && intp(r=pref[0]) && (random(100)<r) )
00307   {
00308     enemy=pref[1+random(sz-1)];
00309 
00310     if ( !objectp(enemy) )
00311     {
00312       pref-=({enemy});
00313 
00314       if ( sizeof(pref)<2 )
00315         pref=0;
00316 
00317       SetProp(P_PREFERED_ENEMY,pref);
00318 
00319       return 0;
00320     }
00321 
00322     if ( !IsEnemy(enemy) )
00323       return 0;
00324   }
00325 
00326   return enemy;
00327 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public void RemoveDefender ( object  friend  ) 

Definiert in Zeile 894 der Datei combat.c.

Benutzt P_DEFENDERS, QueryProp() und SetProp().

00895 { object *defs;
00896 
00897   if ( !objectp(friend) )
00898     return;
00899 
00900   if ( !pointerp(defs=QueryProp(P_DEFENDERS)) )
00901     defs=({});
00902 
00903   if ( member(defs,friend)==-1 )
00904     return;
00905 
00906   defs -= ({friend});
00907   SetProp(P_DEFENDERS,defs);
00908 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public varargs void RemoveResistanceModifier ( string  add  ) 

Definiert in Zeile 142 der Datei combat.c.

Benutzt m_delete(), P_RESISTANCE_MODIFIER, Query(), Set() und UpdateResistanceStrengths().

00143 { string  key;
00144   mapping res;
00145 
00146   if ( !previous_object() )
00147     return;
00148 
00149   key = explode(object_name(previous_object()),"#")[0];
00150 
00151   if ( add )
00152     key += ("#"+add);
00153 
00154   if ( !mappingp(res = Query(P_RESISTANCE_MODIFIER)) )
00155     return;
00156 
00157   efun::m_delete(res, key);
00158   Set(P_RESISTANCE_MODIFIER, res);
00159   UpdateResistanceStrengths();
00160 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public varargs object SelectEnemy ( object *  here  ) 

Definiert in Zeile 360 der Datei combat.c.

Benutzt PresentEnemies() und QueryPreferedEnemy().

Wird benutzt von find_best_combat_command(), heart_beat(), SelectFarEnemy() und SelectNearEnemy().

00361 { object enemy;
00362 
00363   if ( !pointerp(here) )
00364     here=PresentEnemies();
00365 
00366   if ( !sizeof(here) )
00367     return 0;
00368 
00369   if ( !objectp(enemy=QueryPreferedEnemy())
00370       || (environment(enemy)!=environment()) )
00371     enemy=here[random(sizeof(here))];
00372 
00373   return enemy;
00374 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public mapping SetEnemies ( object *  myenemies  ) 

Definiert in Zeile 1643 der Datei combat.c.

Benutzt enemies.

01644 {
01645   enemies=mkmapping(myenemies[0],myenemies[1]);
01646   return enemies;
01647 }

protected void SkillResTransfer ( mapping  from_M,
mapping  to_M 
)

Definiert in Zeile 579 der Datei combat.c.

Benutzt SI_SKILLDAMAGE, SI_SKILLDAMAGE_MSG, SI_SKILLDAMAGE_MSG2, SI_SKILLDAMAGE_TYPE und SI_SPELL.

Wird benutzt von Attack() und shoot_dam().

00580 {
00581   if ( !mappingp(from_M) || !mappingp(to_M) )
00582     return;
00583 
00584   if ( member(from_M,SI_SKILLDAMAGE) )
00585     to_M[SI_SKILLDAMAGE] = (int)from_M[SI_SKILLDAMAGE];
00586 
00587   if ( member(from_M,SI_SKILLDAMAGE_MSG) )
00588     to_M[SI_SKILLDAMAGE_MSG] = (string)from_M[SI_SKILLDAMAGE_MSG];
00589 
00590   if ( member(from_M,SI_SKILLDAMAGE_MSG2) )
00591     to_M[SI_SKILLDAMAGE_MSG2] = (string)from_M[SI_SKILLDAMAGE_MSG2];
00592 
00593   if ( member(from_M,SI_SKILLDAMAGE_TYPE) )
00594     to_M[SI_SKILLDAMAGE_TYPE] = from_M[SI_SKILLDAMAGE_TYPE];
00595 
00596   if ( member(from_M,SI_SPELL) )
00597     to_M[SI_SPELL] = from_M[SI_SPELL];
00598 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public int SpellDefend ( object  caster,
mapping  sinfo 
)

Definiert in Zeile 1756 der Datei combat.c.

Benutzt P_MAGIC_RESISTANCE_OFFSET, QueryProp(), SI_ENEMY, SI_MAGIC_TYPE, SI_SKILLARG, SK_SPELL_DEFEND und UseSkill().

Wird benutzt von feuerball(), identifiziere(), kampfschrei(), pfeil(), saeurestrahl() und schaetz().

01757 { int    re;
01758   mixed  res;
01759   string *ind;
01760 
01761   re = UseSkill(SK_SPELL_DEFEND,([ SI_SKILLARG : sinfo ,
01762                                    SI_ENEMY    : caster ]) );
01763 
01764   if ( (res=QueryProp(P_MAGIC_RESISTANCE_OFFSET)) && mappingp(res)
01765       && pointerp(sinfo[SI_MAGIC_TYPE]))
01766   {
01767     ind = m_indices(res) & sinfo[SI_MAGIC_TYPE];
01768 
01769     if (pointerp(ind) && sizeof(ind) ) {
01770       foreach(string index : ind)
01771         re+=res[index];
01772     }
01773   }
01774   else if(res && intp(res))
01775     re+=res;
01776 
01777   if ( (re>3333) && query_once_interactive(this_object()) )
01778     re=3333; /* Maximal 33% Abwehrchance bei Spielern */
01779   return re;
01780 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public varargs int StopHuntFor ( object  arg,
int  silent 
)

Definiert in Zeile 551 der Datei combat.c.

Benutzt enemies, IsEnemy(), last_attack_msg, m_delete() und StopHuntText().

Wird benutzt von heart_beat(), StopHuntID() und update_hunt_times().

00552 {
00553   if ( !objectp(arg) || !IsEnemy(arg) )
00554     return 0;
00555 
00556   if (!silent)
00557     StopHuntText(arg);
00558 
00559   efun::m_delete(enemies,arg);
00560   last_attack_msg=0;
00561 
00562   return 1;
00563 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public varargs int StopHuntID ( string  str,
int  silent 
)

Definiert in Zeile 1740 der Datei combat.c.

Benutzt enemies und StopHuntFor().

01740                                                       { 
01741 
01742   if ( !stringp(str) )
01743     return 0;
01744 
01745   int j;
01746   foreach(object en: enemies) {
01747     if (en->id(str)) {
01748       StopHuntFor(en,silent);
01749       j++;
01750     }
01751   }
01752 
01753   return j;
01754 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

public varargs mixed StopHuntingMode ( int  silent  ) 

Definiert in Zeile 1619 der Datei combat.c.

Wird benutzt von init() und Pacify().

01620 { mapping save_enemy;
01621   int     i;
01622 
01623   save_enemy=enemies;
01624   if ( !silent )
01625     walk_mapping(enemies, #'StopHuntText); //#');
01626 
01627   enemies=m_allocate(0,1);
01628   last_attack_msg=0;
01629 
01630   return save_enemy;
01631 }

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public void StopHuntText ( object  arg  ) 

Definiert in Zeile 542 der Datei combat.c.

Benutzt ME, Name(), P_PLURAL, QueryProp(), WEN und WER.

Wird benutzt von StopHuntFor().

00543 {
00544   tell_object(arg,
00545     Name(WER,1)+" "+(QueryProp(P_PLURAL)?"jagen ":"jagt ")+
00546                (arg->QueryProp(P_PLURAL)?"Euch":"Dich")+" nicht mehr.\n");
00547   tell_object(ME,(QueryProp(P_PLURAL)?"Ihr jagt ":"Du jagst ")+
00548                  arg->name(WEN,1)+" nicht mehr.\n");
00549 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

protected void update_hunt_times ( int  beats  ) 

Definiert in Zeile 528 der Datei combat.c.

Benutzt enemies und StopHuntFor().

Wird benutzt von catch_up_hbs().

00528                                             {
00529   if (!mappingp(enemies)) return;
00530   foreach(object en, int htime: &enemies) { // Mapping-Keys in en
00531     htime -= beats;
00532     if ( htime <= 0 )
00533       StopHuntFor(en);
00534   }
00535 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public void UpdateResistanceStrengths (  ) 

Definiert in Zeile 81 der Datei combat.c.

Benutzt m_delete(), ob(), P_RESISTANCE_MODIFIER, Query() und Set().

Wird benutzt von _query_resistance_strengths(), AddResistanceModifier() und RemoveResistanceModifier().

00081                                         { 
00082   mapping resmods, strmap;
00083 
00084   if ( !mappingp(resmods=Query(P_RESISTANCE_MODIFIER)) )
00085     return;
00086 
00087   //erstmal die alte Aufsummation loeschen
00088   efun::m_delete(resmods,"me");
00089 
00090   //wenn jetzt leer: Abbruch, keine Res-Modifier da.
00091   if (!sizeof(resmods))
00092       return(Set(P_RESISTANCE_MODIFIER,0));
00093 
00094   strmap = ([]);
00095 
00096   // ueber alle gesetzten ResModifier gehen
00097   foreach(string mod, mapping resmap, object ob: resmods) {
00098     if ( !mappingp(resmap) || !sizeof(resmap)
00099         || !objectp(ob) ) {
00100       efun::m_delete(resmods, mod);
00101       continue; // Resi ungueltig, weg damit.
00102     }
00103     // jetzt noch ueber die Submappings laufen, die die Resis der Objekte
00104     // beinhalten.
00105     foreach(string reskey, float resi: resmap) {
00106                 strmap[reskey] = ((strmap[reskey]+1.0)*(resi+1.0))-1.0;
00107     }
00108   }
00109 
00110   if ( !sizeof(strmap) )
00111     Set(P_RESISTANCE_MODIFIER, 0);
00112   else
00113     Set(P_RESISTANCE_MODIFIER, resmods+([ "me" : strmap; 0 ]) );
00114 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:

public varargs int UseHands ( object  ob,
int  num 
)

Definiert in Zeile 1941 der Datei combat.c.

Benutzt h, i, P_HANDS, P_HANDS_USED_BY, P_MAX_HANDS, QueryProp() und SetProp().

Wird benutzt von _clone_items() und _set_used_hands().

01942 { mixed *h;
01943 
01944   if ( !ob && !(ob=previous_object(1)) )
01945     return 0;
01946 
01947   if ( (num<=0) && ((num=ob->QueryProp(P_HANDS))<=0) )
01948     return 0;
01949 
01950   h=QueryProp(P_HANDS_USED_BY)-({ob});
01951 
01952   if ( (sizeof(h)+num)>QueryProp(P_MAX_HANDS) )
01953     return 0;
01954 
01955   foreach(int i: num)
01956     h+=({ob});
01957 
01958   SetProp(P_HANDS_USED_BY,h);
01959 
01960   return 1;
01961 }

Hier ist ein Graph der zeigt, was diese Funktion aufruft:

Hier ist ein Graph der zeigt, wo diese Funktion aufgerufen wird:


Variablen-Dokumentation

private nosave int att2_time

Definiert in Zeile 47 der Datei combat.c.

Wird benutzt von Attack2() und create().

private nosave int attack_busy

Definiert in Zeile 44 der Datei combat.c.

Wird benutzt von _query_attack_busy(), _set_attack_busy(), create() und heart_beat().

nosave mapping enemies
inherit std living inventory

Definiert in Zeile 12 der Datei combat.c.

private nosave string last_attack_msg

Definiert in Zeile 48 der Datei combat.c.

Wird benutzt von Attack(), InsertSingleEnemy() und StopHuntFor().

private nosave string magic_attack

Definiert in Zeile 43 der Datei combat.c.

private nosave object* missing_attacks

Definiert in Zeile 49 der Datei combat.c.

Wird benutzt von ExecuteMissingAttacks() und InitAttack().

nosave int no_more_attacks

Definiert in Zeile 45 der Datei combat.c.

Wird benutzt von Attack(), ExtraAttack() und heart_beat().

private nosave mapping peace_tries

Definiert in Zeile 50 der Datei combat.c.

Wird benutzt von create().

private nosave mapping QABTCache

Definiert in Zeile 52 der Datei combat.c.

Wird benutzt von _set_armours() und QueryArmourByType().

private nosave int remaining_heart_beats

Definiert in Zeile 46 der Datei combat.c.

Wird benutzt von heart_beat().

inherit std living team
Erzeugt am Thu Jun 3 14:41:13 2010 für MorgenGrauen Mudlib von  doxygen 1.6.3