#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>
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 |
| #define DEBUG | ( | x | ) |
if (find_object("zesstra")) \ tell_object(find_player("zesstra"),x)
| #define HUNTTIME 300 |
Definiert in Zeile 35 der Datei combat.c.
Wird benutzt von heart_beat() und InsertSingleEnemy().
| 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.
| [in,out] | ph | Mapping aus P_PEACE_HISTORY. Wird direkt aktualisiert. |
Definiert in Zeile 2144 der Datei combat.c.
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 }


| private string _kill_alias | ( | string | str | ) |
| 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 }

| 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 }

| 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 }

| 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 }

| 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 }

| 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 }

| 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 }

| 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 }

| 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 }

| 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 }

| static mixed _set_hands | ( | mixed | h | ) | [static] |
| 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 }

| 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 }

| 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 }

| static int _set_wimpy | ( | int | i | ) | [static] |
| 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 }

| 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 }

| 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 }


| 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 }


| public int CheckEnemy | ( | object | ob | ) |
| 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 }

| 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 }

| 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 }

| 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 }

| public mixed EnemyPresent | ( | ) |
| 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 }


| 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 }


| 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 }

| 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 }


| 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 }


| public mapping GetEnemies | ( | ) |
| 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

| 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 }


| 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 }

| 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 }


| 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 }

| 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 }


| 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 }

| protected void InternalModifyDefend | ( | int | dam, | |
| mixed | dt, | |||
| mapping | spell, | |||
| object | enemy | |||
| ) |
| 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 }

| 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 }


| 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 }

| 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
| [in] | caster | Derjenige, der den Spruch ausfuehrt. |
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 }

| 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 }


| 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 }

| public mixed QueryEnemies | ( | ) |
| 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 }


| 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 }

| 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 }

| 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 }


| public mapping SetEnemies | ( | object * | myenemies | ) |
| 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 }

| 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 }


| 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 }


| 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 }

| 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 }

| 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 }


| 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 }


| 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 }


| 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 }


| private nosave int att2_time |
| 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 |
Definiert in Zeile 42 der Datei combat.c.
Wird benutzt von create(), EnemyPresent(), GetEnemies(), heart_beat(), InsertSingleEnemy(), IsEnemy(), Pacify(), PresentEnemies(), QueryEnemies(), SetEnemies(), StopHuntFor(), StopHuntID() und update_hunt_times().
| 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 |
| 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 |
| 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 |
Definiert in Zeile 13 der Datei combat.c.
Wird benutzt von AssocMember(), DeAssocMember(), FindGroup(), InsertEnemyTeam(), InsertSingleEnemy(), is_in_team(), IsTeamLeader(), PresentEnemyRows(), PresentPosition(), PresentTeamRows(), SelectNearEnemy(), team_aufnahme(), teamcmd(), TeamFlee(), TeamMembers(), TeamPrefix() und TryDefaultAttackSpell().
1.6.3