MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // MorgenGrauen MUDlib |
| 2 | // |
| 3 | // armour/combat.c -- armour standard object |
| 4 | // |
| 5 | // $Id: combat.c 9092 2015-01-19 23:57:50Z Zesstra $ |
| 6 | |
| 7 | #pragma strict_types |
| 8 | #pragma save_types |
| 9 | #pragma no_clone |
| 10 | #pragma pedantic |
| 11 | #pragma range_check |
| 12 | |
| 13 | #define NEED_PROTOTYPES |
| 14 | |
| 15 | #include <thing/properties.h> |
| 16 | #include <thing/commands.h> |
| 17 | #include <thing/description.h> |
| 18 | #include <config.h> |
| 19 | #include <combat.h> |
| 20 | #include <language.h> |
| 21 | #include <defines.h> |
| 22 | #include <new_skills.h> |
| 23 | |
| 24 | |
| 25 | // Globale Variablen |
| 26 | private nosave closure defend_cl; |
| 27 | private nosave mapping resistance_strengths=([]); |
| 28 | |
| 29 | void create() { |
| 30 | // Einige Grundwerte setzen |
| 31 | Set(P_ARMOUR_TYPE, AT_ILLEGAL, F_VALUE); |
| 32 | Set(P_LAST_USE,time(),F_VALUE); |
| 33 | } |
| 34 | |
| 35 | // Die Funktion, die den Schutzwert berechnet, den die Ruestung bietet |
| 36 | int QueryDefend(string|string* dam_type, int|mapping spell, object enemy) |
| 37 | { |
| 38 | int prot; |
| 39 | mixed def_func; |
| 40 | object pl; |
| 41 | // Zum Cachen von spell[EINFO_DEFEND], haeufiges Lookup aus dem Mapping |
| 42 | // koennte unnoetig Zeit kosten. |
| 43 | mapping einfo; |
| 44 | |
| 45 | // AT_MISC-Ruetungen schuetzen normalerweise gar nicht... |
| 46 | if (QueryProp(P_ARMOUR_TYPE)==AT_MISC) { |
| 47 | // es sei denn, sie haben eine spezielle DefendFunc |
| 48 | if (!closurep(defend_cl)) return(0); |
| 49 | } |
| 50 | else { |
| 51 | // ansonsten Ruestungsschutz ermitteln und in EINFO_DEFEND vermerken. |
| 52 | // (Beides fuer AT_MISC in jedem Fall unnoetig) |
| 53 | |
| 54 | // Ruestungen schuetzen nur gegen physikalischen Schaden |
| 55 | if ((!spell || (mappingp(spell) && spell[SP_PHYSICAL_ATTACK])) |
| 56 | && sizeof(filter(dam_type,PHYSICAL_DAMAGE_TYPES))) |
| 57 | { |
| 58 | // Schutz bestimmen, Minimum 1, aber nur wenn P_AC > 0 |
| 59 | int pac = QueryProp(P_AC); |
| 60 | if (pac > 0) |
| 61 | prot = (pac/4 + random(pac*3/4 + 1)) || 1 ; |
| 62 | object stat = find_object("/d/erzmagier/zesstra/pacstat"); |
| 63 | if (stat) |
| 64 | stat->acstat(QueryProp(P_ARMOUR_TYPE),prot, |
| 65 | random(pac)+1); |
| 66 | |
| 67 | // ruestungschutz an defendfunc weitermelden |
| 68 | if (mappingp(spell) && |
| 69 | mappingp(einfo=spell[EINFO_DEFEND])) { |
| 70 | // Schutz d. akt. Ruestung vermerken. |
| 71 | einfo[DEFEND_CUR_ARMOUR_PROT]=prot; |
| 72 | // daten der Ruestung vermerken. |
| 73 | if (mappingp(einfo[DEFEND_ARMOURS])) { |
| 74 | einfo[DEFEND_ARMOURS][ME,DEF_ARMOUR_PROT]=prot; |
| 75 | } |
| 76 | } // ende vom if (mapping(spell) ...) |
| 77 | } // ende vom if (phys Schaden) |
| 78 | |
| 79 | } // ende vom else (wenn kein AT_MISC) |
| 80 | |
| 81 | // Ist eine DefendFunc gesetzt, wird diese ausgewertet |
| 82 | if (closurep(defend_cl)) { |
| 83 | if (!objectp(get_type_info(defend_cl,2))) { |
| 84 | // Closure gesetzt, aber nicht gueltig, schauen, ob wir sie neu |
| 85 | // erstellen koennen. |
| 86 | if (objectp(def_func=QueryProp(P_DEFEND_FUNC))) { |
| 87 | defend_cl=symbol_function("DefendFunc",def_func); |
| 88 | } |
| 89 | // sonst loeschen, um spaeter diesen Zweig ganz zu sparen. |
| 90 | else defend_cl=0; |
| 91 | } |
| 92 | // BTW: Es ist ok, wenn defend_cl jetzt 0 ist, dann liefert funcall() |
| 93 | // auch 0. |
| 94 | // Bei Netztoten keine (zurueckschlagende) DefendFunc |
| 95 | if (objectp(pl=QueryProp(P_WORN)) && (!query_once_interactive(pl) || |
| 96 | interactive(pl)) ) { |
| 97 | // Der Rueckgabewert der DefendFunc wird zum Schutz addiert |
| 98 | prot += funcall(defend_cl, dam_type, spell, enemy); |
| 99 | // leider kann die DefendFunc jetzt auch noch das Objekt zerstoert |
| 100 | // haben... |
| 101 | if (!objectp(this_object())) |
| 102 | return prot; |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | // Zeitpunkt der letzten Benutzung ausgeben |
| 107 | SetProp(P_LAST_USE,time()); |
| 108 | |
| 109 | // Berechneten Schutz zurueckgeben |
| 110 | return prot; |
| 111 | } |
| 112 | |
| 113 | // Es duerfen nur "legale" Ruestungstypen gesetzt werden, ansonsten |
| 114 | // wird AT_ILLEGAL gesetzt. |
| 115 | static mixed _set_armour_type(mixed type ) { |
| 116 | if (!COMBAT_MASTER->valid_armour_type(type)) |
| 117 | { |
| 118 | Set(P_ARMOUR_TYPE, (type=AT_ILLEGAL), F_VALUE); |
| 119 | } |
| 120 | else |
| 121 | { |
| 122 | Set(P_ARMOUR_TYPE, type); |
| 123 | } |
| 124 | AddId(type); |
| 125 | |
| 126 | resistance_strengths=([]); |
| 127 | return type; |
| 128 | } |
| 129 | |
| 130 | |
| 131 | // Wird etwas an P_DEFEND_FUNC geaendert, muss die zugehoerige closure |
| 132 | // neu erstellt werden. |
| 133 | static object _set_defend_func(object arg) { |
| 134 | if (objectp(arg) && |
| 135 | closurep(defend_cl=symbol_function("DefendFunc",arg))) { |
| 136 | return Set(P_DEFEND_FUNC, arg, F_VALUE); |
| 137 | } |
| 138 | defend_cl=0; |
| 139 | return(Set(P_DEFEND_FUNC, 0, F_VALUE)); |
| 140 | } |
| 141 | |
| 142 | // Auch Ruestungen koennen einen Schadenstyp haben. Dieser kann als string |
| 143 | // oder array angegeben werden, wird aber intern auf jeden Fall als |
| 144 | // array gespeichert. |
| 145 | static mixed _set_dam_type(mixed arg) { |
| 146 | if (pointerp(arg)) |
| 147 | { |
| 148 | return Set(P_DAM_TYPE, arg, F_VALUE); |
| 149 | } |
| 150 | else if (stringp(arg)) |
| 151 | { |
| 152 | return Set(P_DAM_TYPE, ({ arg }), F_VALUE); |
| 153 | } |
| 154 | return Query(P_DAM_TYPE, F_VALUE); |
| 155 | } |
| 156 | |
| 157 | // Ruestungen koennen Resistenzen setzen. Diese werden jedoch nicht wie |
| 158 | // "normale" Resistenzen gesetzt, sondern als Prozentwerte der fuer diesen |
| 159 | // Typ maximal zulaesigen Resistenz. Die Aenderung der Resistenzen darf |
| 160 | // nur durch die Ruestung selbst erfolgen. |
| 161 | // Beispiel: ([DT_FIRE: 100, DT_WATER: -150]) |
| 162 | // max. Feuerresistenz, 1.5fache Anfaelligkeit |
| 163 | static mixed _set_resistance_strengths(mixed resmap) { |
| 164 | float max_res; |
| 165 | object worn_by; |
| 166 | |
| 167 | // Es duerfen nur mappings angegeben werden |
| 168 | if (!mappingp(resmap)) |
| 169 | { |
| 170 | return -1; |
| 171 | } |
| 172 | |
| 173 | // die Maxwerte muessen jeweils durch -100 geteilt sein, da hinterher |
| 174 | // mit der Prozentzahl multipliziert wird und die angabe der Vorzeichen |
| 175 | // hier umgekehrt wie bei den "normalen" Resistenzen ist. Der |
| 176 | // Maximalwert ist vom Ruestungstyp abhaengig. |
| 177 | switch (QueryProp(P_ARMOUR_TYPE)) |
| 178 | { |
| 179 | case AT_CLOAK : |
| 180 | case AT_RING : |
| 181 | case AT_AMULET : max_res=-0.0010; |
| 182 | break; |
| 183 | case AT_SHIELD : |
| 184 | case AT_ARMOUR : max_res=-0.0015; |
| 185 | break; |
| 186 | default : max_res=-0.0005; |
| 187 | } |
| 188 | |
| 189 | // Resistenz-Mapping aktualisieren |
| 190 | resistance_strengths=([]); |
| 191 | foreach(string damtype, int res: resmap) |
| 192 | { |
| 193 | if (!intp(res)) res=to_int(res); |
| 194 | // Mehr als 100 Prozent ist nicht erlaubt |
| 195 | if (res>100) |
| 196 | { |
| 197 | res=100; |
| 198 | } |
| 199 | else if (res<0) |
| 200 | { |
| 201 | res=(res/4)*5; |
| 202 | // Man kann auch nicht beliebig negativ werden |
| 203 | if (res<-1000) |
| 204 | { |
| 205 | res=-1000; |
| 206 | } |
| 207 | } |
| 208 | // Der Resistenzwert berechnet sich aus dem Produkt des |
| 209 | // Maximalwertes und der Prozentzahl |
| 210 | resistance_strengths[damtype]=res*max_res; |
| 211 | } |
| 212 | |
| 213 | // Werden die Resistenzen bei einer getragenen Ruestung geaendert, |
| 214 | // muss der Traeger davon natuerlich beeinflusst werden. |
| 215 | if (objectp(worn_by=QueryProp(P_WORN))) |
| 216 | { |
| 217 | worn_by->AddResistanceModifier(resistance_strengths, |
| 218 | QueryProp(P_ARMOUR_TYPE)); |
| 219 | } |
| 220 | return resistance_strengths; |
| 221 | } |
| 222 | |
| 223 | // Bei einem QueryProp(P_RESISTANCE_STRENGTHS) soll das aktuelle |
| 224 | // Resistenzen-Mapping zurueckgegeben werden |
| 225 | static mapping _query_resistance_strengths() { |
| 226 | return (resistance_strengths||([])); |
| 227 | } |
| 228 | |