blob: cb10ff5f410b80fd7c2dd545fd2f0afed619a921 [file] [log] [blame]
// MorgenGrauen MUDlib
//
// weapon/combat.c -- combat part of the weapon standard object
//
// $Id: combat.c 9425 2016-01-02 18:19:40Z Zesstra $
#include <sys_debug.h>
#pragma strict_types
#pragma save_types
#pragma no_clone
#pragma pedantic
#pragma range_check
#define NEED_PROTOTYPES
#include <thing/properties.h>
#include <thing/commands.h>
#include <thing/description.h>
#include <properties.h>
#include <language.h>
#include <combat.h>
#include <attributes.h>
#include <defines.h>
#include <moving.h>
#include <new_skills.h>
// Globale Variablen
int ftime, flaw;
private nosave int logged;
private nosave closure defend_cl, hit_cl;
void create()
{
// Variablen initialisieren
logged=ftime=flaw=0;
defend_cl=0;
hit_cl=0;
// Einige Grundwerte setzen
SetProp(P_WEAPON_TYPE, WT_CLUB);
SetProp(P_DAM_TYPE, ({DT_BLUDGEON}));
SetProp(P_NR_HANDS, 2);
SetProp(P_PARRY,PARRY_NOT);
SetProp(P_AC,0);
Set(P_RESTRICTIONS,([]),F_VALUE);
Set(P_LAST_USE,time(),F_VALUE);
// Einige Properties sollten nicht von aussen gesetzt werden koennen
Set(P_PARRY, PROTECTED, F_MODE_AS);
Set(P_WIELDED, PROTECTED, F_MODE_AS);
Set(P_LAST_USE,PROTECTED, F_MODE_AS);
// Diese kann von aussen gesetzt werden (noch), aber bitte nur ueber die
// hier definierte Setmethode.
Set(P_DAMAGED, PROTECTED, F_MODE_AS);
// Eine Waffe benoetigt Kommandos, mit denen man sie zuecken
// und wegstecken kann
AddCmd( ({"zueck","zuecke","zieh","ziehe"}), "wield" );
AddCmd( ({"steck","stecke"}), "unwield" );
}
// aktuelles Lebewesen, was diese Waffe zur Zeit gezueckt hat.
public object QueryUser()
{
return QueryProp(P_WIELDED);
}
/*
* Ausgabe einer Meldung beim Zuecken geht nur an Spieler, nicht an NPC.
* Die Umgebung bekommt natuerlich immer eine Meldung.
*/
void doWieldMessage()
{
string *str, s1;
if(QueryProp(P_WIELD_MSG)) // Ist eine WieldMsg gesetzt?
{
if(closurep(QueryProp(P_WIELD_MSG))) // Sogar als eigene Fkt.?
{
str = funcall(QueryProp(P_WIELD_MSG),this_player());
if(interactive(this_player()))
{
this_player()->ReceiveMsg(str[0],
MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_WIELD, 0,
this_player());
}
if ( objectp(environment()) && objectp(environment(environment())) )
send_room(environment(environment()),
str[1],
MT_LOOK|MSG_BS_LEAVE_LFS,
MA_WIELD, 0, ({this_player()}), environment());
return;
}
else if(interactive(this_player()))
{
s1 = replace_personal(sprintf(QueryProp(P_WIELD_MSG)[0],"@WEN2"),
({this_player(),this_object()}), 1);
this_player()->ReceiveMsg(s1,
MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_WIELD, 0,
this_player());
}
// Abwaertskompatibel: Das erste %s wird zu WEN1, das zweite zu WEN2
s1 = replace_personal(sprintf(QueryProp(P_WIELD_MSG)[1],"@WEN1","@WEN2"),
({this_player(), this_object()}), 1);
if ( objectp(environment()) && objectp(environment(environment())) )
send_room(environment(environment()),
s1,
MT_LOOK|MSG_BS_LEAVE_LFS,
MA_WIELD, 0, ({this_player()}), environment());
return;
}
/*
* Keine WieldMsg gesetzt, Ausgabe der Default-Meldungen.
*/
else if(interactive(this_player()))
{
this_player()->ReceiveMsg(
"Du zueckst "+name(WEN,1)+".",
MT_NOTIFICATION, MA_WIELD, 0, this_player());
}
//s.o. ersetzt durch tell_room()
//say(break_string(this_player()->Name(WER)+" zueckt "
// +name(WEN,0)+".",78),({ this_player() }));
if ( objectp(environment()) && objectp(environment(environment())) )
send_room(environment(environment()),
this_player()->Name(WER)+" zueckt "+name(WEN,0)+".",
MT_LOOK,
MA_WIELD, 0, ({this_player()}), environment());
}
/*
* Ausgabe einer Meldung beim Wegstecken geht nur an Spieler, nicht an NPC.
* Die Umgebung bekommt immer eine Meldung.
*/
void doUnwieldMessage(object wielded_by)
{
string *str,s1;
if(!objectp(wielded_by)) // Hoops! Gar nicht gezueckt? Abbruch!
{
return;
}
if(QueryProp(P_UNWIELD_MSG)) // Hier gibt es eine UnwieldMsg.
{
if(closurep(QueryProp(P_UNWIELD_MSG))) // Sogar als Closure, wow :-)
{
str = funcall(QueryProp(P_UNWIELD_MSG),wielded_by);
if(interactive(wielded_by))
{
wielded_by->ReceiveMsg(str[0],
MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_UNWIELD, 0, wielded_by);
}
if ( objectp(environment()) && objectp(environment(environment())) )
send_room(environment(environment()),
str[1],
MT_LOOK|MSG_BS_LEAVE_LFS,
MA_UNWIELD, 0, ({wielded_by}), environment());
return;
}
else if(interactive(wielded_by))
{
s1 = replace_personal(sprintf(QueryProp(P_UNWIELD_MSG)[0],"@WEN2"),
({this_player(),this_object()}), 1);
wielded_by->ReceiveMsg(s1,
MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_UNWIELD, 0, wielded_by);
}
s1 = replace_personal(sprintf(QueryProp(P_UNWIELD_MSG)[1],"@WEN1","@WEN2"),
({wielded_by, this_object()}), 1);
if ( objectp(environment()) && objectp(environment(environment())) )
send_room(environment(environment()),
s1,
MT_LOOK|MSG_BS_LEAVE_LFS,
MA_UNWIELD, 0, ({wielded_by}), environment());
return;
}
/*
* Keine UnwieldMsg, also Default-Meldungen ausgeben.
*/
else if(interactive(wielded_by))
{
wielded_by->ReceiveMsg(
"Du steckst "+name(WEN,1)+" zurueck.",
MT_NOTIFICATION, MA_UNWIELD, 0, wielded_by);
}
if ( objectp(environment()) && objectp(environment(environment())) )
send_room(environment(environment()),
wielded_by->Name(WER) +" steckt "+name(WEN,0)+" zurueck.",
MT_LOOK,
MA_UNWIELD, 0, ({wielded_by}), environment());
}
// Diese Funktion wird aufgerufen, wenn die Waffe wirklich gezueckt wird
protected void InformWield(object pl, int silent)
{
return;
}
// Diese Funktion wird aufgerufen, wenn die Waffe wirklich weggesteckt
// wird
protected void InformUnwield(object pl, int silent)
{
return;
}
// wield_me soll knallen.
varargs int wield_me(int silent)
{
raise_error("wield_me() ist veraltet. Bitte nutze DoWield()\n");
return 1;
}
// Die Funktion, die das eigentliche Zuecken durchfuehrt.
varargs int DoWield(int silent)
{ int dex, parry;
closure cl;
mixed res;
// Man kann nur Waffen zuecken, die man auch im Inventory hat.
if (environment()!=PL)
{
_notify_fail( break_string(
"Du musst "+name(WEN,1)+" schon erst nehmen!",78) );
return 0;
}
// Eine gezueckte Waffe kann man natuerlich nicht nochmal zuecken
if (QueryProp(P_WIELDED))
{
notify_fail("Das hast Du schon gemacht!\n");
return 0;
}
// Waffen, die ein oder mehrere Attribut veraendern und gegen
// das gesetzte Limit verstossen, haben keine Wirkung bezueglich der
// Attribute.
if ( mappingp(res=QueryProp(P_M_ATTR_MOD)) && PL->TestLimitViolation(res) )
{
write(break_string(
"Irgendetwas an Deiner Ausruestung verhindert, dass Du Dich mit "+
name(WEM,1)+" so richtig wohl fuehlst.",78));
}
// Ueber P_RESTRICTIONS kann man einige Restriktionen definieren, ohne
// gleich auf eine WieldFunc zurueckgreifen zu muessen.
// Die Auswertung erfolgt ueber den RestrictionChecker
if ( (res=QueryProp(P_RESTRICTIONS)) && mappingp(res) &&
(res=(string)call_other("/std/restriction_checker","check_restrictions",
PL,res)) && stringp(res) )
{
notify_fail(res);
return 0;
}
parry=(int)QueryProp(P_PARRY);
dex=(int)PL->QueryAttribute(A_DEX);
// Testen, ob der Spieler die noetige Geschicklichkeit besitzt, um
// mit dieser (Parier)Waffe umgehen zu koennen
if ( ((parry<PARRY_ONLY) && ((dex+8)*10)<QueryProp(P_WC)) ||
((parry>PARRY_NOT) && ((dex+5)*2 )<QueryProp(P_AC)) )
{
notify_fail(
"Du bist nicht geschickt genug, um mit dieser Waffe umzugehen.\n");
return 0;
}
// Eine Gezueckte Waffe muss natuerlich erst mal weggesteckt werden.
if ( (parry<PARRY_ONLY) && objectp(res=(object)PL->QueryProp(P_WEAPON)) )
{
if ( (res->DoUnwield(silent)) && !((object)PL->QueryProp(P_WEAPON)) )
{
// Wenn die alte Waffe weggesteckt werden konnte, nochmal
// versuchen zu zuecken
return DoWield(silent);
}
else
{
// Sonst Meldung ausgeben
notify_fail("Das geht nicht, solange Du noch eine andere "+
"Waffe gezueckt hast.\n");
return 0;
}
}
// Das gleiche gilt natuerlich fuer Parierwaffen
if ( (parry>PARRY_NOT) && objectp(res=(object)PL->QueryProp(P_PARRY_WEAPON)) )
{
if ( (res->DoUnwield(silent)) && !(PL->QueryProp(P_PARRY_WEAPON)) )
{
// Wenn die alte Parierwaffe weggesteckt werden konnte, nochmal
// versuchen zu zuecken
return DoWield(silent);
}
else
{
// Sonst Meldung ausgeben
notify_fail("Das geht nicht, solange Du noch eine andere "+
"Paierwaffe gezueckt hast.\n");
return 0;
}
}
// Ist eine WieldFunc gesetzt, wird diese aufgerufen.
if (objectp(res=QueryProp(P_WIELD_FUNC))
&& !(res->WieldFunc(ME,silent,environment())))
{
// Eine Meldung sollte schon von der WieldFunc ausgegeben werden.
return 1;
}
// Die zulaessigen Hoechstwerte duerfen natuerlich nicht
// ueberschritten werden.
if ( (parry<PARRY_ONLY) && (QueryProp(P_WC)>MAX_WEAPON_CLASS) )
{
notify_fail(
"Ungueltige Waffenklasse, bitte Erzmagier verstaendigen.\n");
return 0;
}
if ( (parry>PARRY_NOT) && (QueryProp(P_AC)>MAX_PARRY_CLASS) )
{
notify_fail(
"Ungueltige Parierklasse, bitte Erzmagier verstaendigen.\n");
return 0;
}
// Testen, ob der Zuecker genug Haende frei hat.
if (!(PL->UseHands(ME,QueryProp(P_NR_HANDS))))
{
notify_fail("Du hast keine Hand mehr frei.\n");
return 0;
}
// Ok, jetzt ist alles klar, die (Parier)Waffe wird gezueckt
SetProp(P_WIELDED, PL);
SetProp(P_EQUIP_TIME,time());
cl=symbol_function("SetProp",PL);
if (parry<PARRY_ONLY)
{
// Dieses Objekt als Waffe setzen
funcall(cl,P_WEAPON, ME );
}
if (parry>PARRY_NOT)
{
// Dieses Objekt als Parierwaffe setzen
funcall(cl,P_PARRY_WEAPON, ME );
}
// Waffen koennen Attribute aendern/blockieren. Also muessen diese
// nach dem Zuecken aktualisiert werden
PL->register_modifier(ME);
PL->UpdateAttributes();
// P_TOTAL_AC/P_TOTAL_WC im Spieler aktualisieren. Da dort Attribute
// eingehen, kann das erst hier gemacht werden.
if (parry<PARRY_ONLY)
{
PL->QueryProp(P_TOTAL_WC);
}
if (parry>PARRY_NOT)
{
PL->QueryProp(P_TOTAL_AC);
}
// Zueck-Meldung ausgeben, wenn das silent-Flag nicht gesetzt ist
if (!silent)
{
doWieldMessage();
}
// Alle Waffen werden im awmaster registriert, sobald sie von einem
// Spieler gezueckt werden
if (!logged && query_once_interactive(PL))
{
call_other("/secure/awmaster","RegisterWeapon",ME);
logged=1;
}
// Inform-Funktion aufrufen
InformWield(PL,silent);
// Fertig mit dem Zuecken
return 1;
}
// Die Funktion, die das eigentliche Wegstecken durchfuehrt.
varargs int DoUnwield(int silent)
{ closure cl;
int parry;
mixed res;
object wielded_by;
// Waffen, die nicht gezueckt sind, kann man natuerlich nicht
// wegstecken
if (!objectp(wielded_by=QueryProp(P_WIELDED)))
{
return 0;
}
// Ist eine UnwieldFunc gesetzt, wird diese aufgerufen
if ( objectp(res=QueryProp(P_UNWIELD_FUNC)) &&
!(res->UnwieldFunc(ME,silent,wielded_by)) )
{
// Eine Meldung muss die UnwieldFunc schon selbst ausgeben.
return 1;
}
// Eine verfluchte Waffe kann man natuerlich nicht wegstecken - aber
// auch da gibts Ausnahmefaelle, wie z.B. den Tod eines Spielers
if ((res=QueryProp(P_CURSED)) && !(silent&M_NOCHECK))
{
if (stringp(res))
{
// Stand in P_CURSED ein String? Dann diesen ausgeben
tell_object(wielded_by,
(res[<1]=='\n' ? res : break_string(res,78)));
}
else
{
// Sonst eine Standard-Meldung ausgeben
tell_object(wielded_by, break_string(
"Du kannst "+name(WEN)+" nicht wegstecken.",78));
}
return 1;
}
// Ok, jetzt ist alles klar, die (Parier)Waffe wird weggesteckt
parry=QueryProp(P_PARRY);
cl=symbol_function("SetProp",wielded_by);
if (parry<PARRY_ONLY)
{
// Eintrag als Waffe im Spieler loeschen
funcall(cl,P_WEAPON, 0);
}
if (parry>PARRY_NOT)
{
// Eintrag als Parierwaffe im Spieler loeschen
funcall(cl,P_PARRY_WEAPON, 0);
}
// Im Spieler die Zeit setzen, zu der er zuletzt eine Waffe weggesteckt
// hat.
funcall(cl,P_UNWIELD_TIME,time());
// Meldung ausgeben, wenn silent-Flag nicht gesetzt ist
if (!silent)
{
doUnwieldMessage(wielded_by);
}
// Die Haende, die bisher von der Waffe benutzt wurden, freigeben
wielded_by->FreeHands(ME);
SetProp(P_WIELDED, 0);
// Waffen koennen Attribute aendern/blockieren. Also muessen diese
// nach dem Wegstecken aktualisiert werden
wielded_by->deregister_modifier(ME);
wielded_by->UpdateAttributes();
// P_TOTAL_AC/P_TOTAL_WC im Spieler aktualisieren. Da dort Attribute
// eingehen, kann das erst hier gemacht werden.
if (parry<PARRY_ONLY)
{
wielded_by->QueryProp(P_TOTAL_WC);
}
if (parry>PARRY_NOT)
{
wielded_by->QueryProp(P_TOTAL_AC);
}
// Inform-Funktion aufrufen
InformUnwield(wielded_by, silent);
// Fertig mit dem Wegstecken
return 1;
}
// Die Funktion, die das "zuecken"-Kommando auswertet
varargs int wield(string str, int silent)
{
if ( !stringp(str) ||
(query_verb()[0..3]=="zieh" && sscanf(str,"%s hervor",str)!=1) )
{
return 0;
}
if (!id(str))
{
_notify_fail("Du hast sowas nicht.\n");
return 0;
}
return DoWield(silent);
}
// Die Funktion, die das "wegstecken"-Kommando auswertet
int unwield(string str)
{ int parry;
string dummy;
// Erstmal die Eingabe auswerten. Ist dies wirklich ein Kommando
// zum Wegstecken?
if ( !stringp(str) || (sscanf(str,"%s weg", dummy)!=1 &&
sscanf(str,"%s ein", dummy)!=1 &&
sscanf(str,"%s zurueck", dummy)!=1 ) )
{
return 0;
}
str = dummy;
parry=QueryProp(P_PARRY);
// Ist wirklich diese Waffe gemeint?
if ( !stringp(str) || !id(str) ||
((parry<PARRY_ONLY)&&((object)PL->QueryProp(P_WEAPON)!=ME)) ||
((parry>PARRY_NOT)&&((object)PL->QueryProp(P_PARRY_WEAPON)!=ME)) )
{
return 0;
}
// Man kann nur Waffen wegstecken, die man auch bei sich hat
if (environment() != PL)
{
_notify_fail("Diese Waffe gehoert Dir nicht!\n");
return 0;
}
// Und natuerlich geht das auch nur, wenn die Waffe gezueckt ist.
if (!QueryProp(P_WIELDED))
{
_notify_fail("Diese Waffe hast Du gar nicht gezueckt ...\n");
return 0;
}
return DoUnwield();
}
// Die Funktion, die den Schaden berechnet, den die Waffe verursacht
int QueryDamage(object enemy)
{ int dam;
mixed hit_func;
object wielder;
// Nur gezueckte Waffen machen Schaden
if (!objectp(wielder=QueryProp(P_WIELDED)))
return 0;
// Den Basis-Schaden berechnen. Die Staerke des Benutzers wird
// hier beruecksichtigt.
dam = (2*QueryProp(P_WC)+10*((int)wielder->QueryAttribute(A_STR)))/3;
// Wie gut man getroffen hat, wird ueber ein random() simuliert
dam = random(1+dam);
// Ist eine HitFunc gesetzt, dann wird diese ausgewertet. Der
// Rueckgabe-Wert wird zum Schaden addiert
if (!hit_cl || !get_type_info(hit_cl,2))
{
if (objectp(hit_func=QueryProp(P_HIT_FUNC)))
{
hit_cl=symbol_function("HitFunc",hit_func);
}
}
if (hit_cl && get_type_info(hit_cl,2))
{
dam += funcall(hit_cl,enemy);
}
// Zeitpunkt der letzten Benutzung ausgeben
SetProp(P_LAST_USE,time());
// Berechneten Schaden zurueckgeben
return dam;
}
// Die Funktion, die bei Parierwaffen den Schutzwert berechnet.
int QueryDefend(string* dam_type, mixed spell, object enemy)
{ int prot;
mixed def_func;
object pl;
prot = 0;
// Ruestungen schuetzen nur gegen physikalischen Schaden
if (!spell || (mappingp(spell) && spell[SP_PHYSICAL_ATTACK]))
{
if (sizeof(filter(dam_type,PHYSICAL_DAMAGE_TYPES)))
{
prot = random(1+QueryProp(P_AC));
}
}
// Ist eine DefendFunc gesetzt, wird diese ausgewertet
if (!defend_cl || !get_type_info(defend_cl,2))
{
if (objectp(def_func=QueryProp(P_DEFEND_FUNC)))
{
defend_cl=symbol_function("DefendFunc",def_func);
}
}
//Bei Netztoten keine (zurueckschlagende) DefendFunc
if (defend_cl && get_type_info(defend_cl,2) &&
objectp(pl=QueryProp(P_WIELDED)) && (!query_once_interactive(pl) ||
interactive(pl)) )
{
// Der Rueckgabewert der DefendFunc wird zum Schutz addiert
prot += funcall(defend_cl, dam_type, spell, enemy);
}
// Zeitpunkt der letzten Benutzung ausgeben
SetProp(P_LAST_USE,time());
// Berechneten Schutz zurueckgeben
return prot;
}
// Die Anzahl der von einer Waffe benoetigten Haende darf natuerlich nicht
// kleiner als 1 sein.
int _set_nr_hands(int arg)
{
if (!intp(arg) || (arg<1) )
return Query(P_NR_HANDS, F_VALUE);
return Set(P_NR_HANDS, arg, F_VALUE);
}
// Der Schadenstyp einer Waffe darf zwar als string angegeben werden, wird
// intern aber immer als array gespeichert
mixed _set_dam_type(mixed arg)
{
if (pointerp(arg))
{
return Set(P_DAM_TYPE, arg, F_VALUE);
}
else if (stringp(arg))
{
return Set(P_DAM_TYPE, ({ arg }), F_VALUE);
}
return Query(P_DAM_TYPE, F_VALUE);
}
// Objekte, die die Beschaedigung einer Waffe durch direktes Setzen von
// P_DAMAGED durchfuehren, werden im awmaster geloggt
mixed _set_item_damaged(mixed arg)
{
if (arg && !intp(arg))
{
return Query(P_DAMAGED, F_VALUE);
}
if (previous_object(1))
call_other("/secure/awmaster","RegisterDamager",
previous_object(1),QueryProp(P_DAMAGED),arg);
return Set(P_DAMAGED,arg,F_VALUE);
}
// Wird etwas an P_HIT_FUNC geaendert, muss die zugehoerige closure
// erstmal geloescht werden.
mixed _set_hit_func(mixed arg)
{
hit_cl=0;
return Set(P_HIT_FUNC, arg, F_VALUE);
}
// Wird etwas an P_DEFEND_FUNC geaendert, muss die zugehoerige closure
// erstmal geloescht werden.
mixed _set_defend_func(mixed arg)
{
defend_cl=0;
return Set(P_DEFEND_FUNC, arg, F_VALUE);
}
// Die maximale Waffenklasse einer Waffe berechnet sich natuerlich aus
// der aktuellen Waffenklasse und der Beschaedigung. Eine Ausnahme bilden
// hier Waffen, deren effektive Waffenklasse groesser ist als diese Summe
int _query_max_wc()
{ int a,b;
a=QueryProp(P_WC)+QueryProp(P_DAMAGED);
b=QueryProp(P_EFFECTIVE_WC);
if (b>a)
return b;
return a;
}
// Will man eine Waffe beschaedigen oder reparieren, so macht man das
// am besten ueber die Funktion Damage(argument). Positive Argumente
// bedeuten eine Beschaedigung, negative eine Reparatur. Der Rueckgabewert
// ist die wirklich durchgefuehrte Aenderung des Beschaedigungswertes
int Damage(int new_dam)
{ int wc,old_dam;
object w;
// Uebergebenes Argument pruefen
if (!new_dam || !intp(new_dam))
{
return 0;
}
// Bei Waffen, die nicht ausschliesslich zur Parade eingesetzt werden,
// geht die Beschaedigung auf die Kampfkraft, sprich: P_WC
if (QueryProp(P_PARRY)<PARRY_ONLY)
{
if ((wc=QueryProp(P_WC))<=MIN_WEAPON_CLASS && new_dam>0)
{
// Sonst wuerde Beschaedigung zur Reparatur fuehren
return 0;
}
// Min-WC und Max-WC beachten
if ((wc-new_dam) < MIN_WEAPON_CLASS)
{
new_dam = wc-MIN_WEAPON_CLASS;
}
else if ((wc-new_dam) > MAX_WEAPON_CLASS)
{
new_dam = wc-MAX_WEAPON_CLASS;
}
// Nie mehr als 100% reparieren
if (((old_dam=QueryProp(P_DAMAGED))<-new_dam) && new_dam<0)
{
new_dam=-old_dam;
}
// Aenderungen an der Waffenklasse und der dem Beschaedigungswert
// durchfuehren
SetProp(P_WC,(wc-new_dam));
// Ausnahmeweise Set, um die loggende Setmethode zu umgehen.
// TODO: SetProp, sobald direktes Beschaedigen raus ist.
Set(P_DAMAGED, old_dam+new_dam, F_VALUE);
// P_TOTAL_WC im Traeger updaten, so vorhanden
if (objectp(w=QueryProp(P_WIELDED)))
w->QueryProp(P_TOTAL_WC);
// Rueckgabewert: Durchgefuehrte Aenderung an P_DAMAGE
return new_dam;
}
// Bei reinen Parierwaffen geht die Beschaedigung auf die
// Schutzwirkung, sprich: P_AC
if ((wc=QueryProp(P_AC))<=0 && new_dam>0)
{
// Sonst wuerde Beschaedigung zur Reparatur fuehren
return 0;
}
// Min-AC=0 und Max-AC beachten
if ((wc-new_dam) < MIN_PARRY_CLASS)
{
new_dam = wc-MIN_PARRY_CLASS;
}
else if ((wc-new_dam) > MAX_PARRY_CLASS)
{
new_dam = wc-MAX_PARRY_CLASS;
}
// Nie mehr als 100% reparieren
if (((old_dam=QueryProp(P_DAMAGED))<-new_dam) && new_dam<0)
{
new_dam=-old_dam;
}
// Aenderungen an der Ruestungsklasse und dem Beschaedigungswert
// durchfuehren
SetProp(P_AC,wc-new_dam);
// Ausnahmeweise Set, um die loggende Setmethode zu umgehen.
// TODO: SetProp, sobald direktes Beschaedigen raus ist.
Set(P_DAMAGED,old_dam+new_dam, F_VALUE);
// P_TOTAL_AC im Traeger updaten, so vorhanden
if (objectp(w=QueryProp(P_WIELDED)))
w->QueryProp(P_TOTAL_AC);
// Rueckgabewert: Durchgefuehrte Aenderung an P_DAMAGE
return new_dam;
}
// Wird die Waffe einer Belastung ausgesetzt (z.B. wenn man damit
// zuschlaegt), dann wird TakeFlaw() aufgerufen.
varargs void TakeFlaw(object enemy)
{ int c;
// Flaw-Wert erhoehen
flaw++;
// Ist der Waffe eine Qualitaet gesetzt worden, so kann es zu einer
// allmaehlichen Beschaedigung der Waffe kommen
if ((c=QueryProp(P_QUALITY)) && !(flaw%c))
Damage(1);
// Zeitpunkt des ersten Aufrufes festhalten
if (!ftime)
ftime=time();
}
// Die Flaw-Daten koennen natuerlich auch abgerufen werden
mixed *QueryFlaw()
{
return({flaw,ftime,dtime(ftime)});
}