// MorgenGrauen MUDlib
//
// armour/combat.c -- armour standard object
//
// $Id: combat.c 9092 2015-01-19 23:57:50Z Zesstra $

#pragma strict_types
#pragma save_types
#pragma no_clone
#pragma range_check

#define NEED_PROTOTYPES

#include <thing/properties.h>
#include <thing/commands.h>
#include <thing/description.h>
#include <config.h>
#include <combat.h>
#include <language.h>
#include <defines.h>
#include <new_skills.h>


// Globale Variablen
private nosave closure defend_cl;
private nosave mapping resistance_strengths=([]);

void create() {
    // Einige Grundwerte setzen
    Set(P_ARMOUR_TYPE, AT_ILLEGAL, F_VALUE);
    Set(P_LAST_USE,time(),F_VALUE);
}

// Die Funktion, die den Schutzwert berechnet, den die Ruestung bietet
int QueryDefend(string|string* dam_type, int|mapping spell, object enemy)
{
    int     prot;
    mixed   def_func;
    object  pl;
    // Zum Cachen von spell[EINFO_DEFEND], haeufiges Lookup aus dem Mapping
    // koennte unnoetig Zeit kosten.
    mapping einfo;

    // AT_MISC-Ruetungen schuetzen normalerweise gar nicht...
    if (QueryProp(P_ARMOUR_TYPE)==AT_MISC) {
        // es sei denn, sie haben eine spezielle DefendFunc
        if (!closurep(defend_cl)) return(0);
    }
    else {
        // ansonsten Ruestungsschutz ermitteln und in EINFO_DEFEND vermerken.
        // (Beides fuer AT_MISC in jedem Fall unnoetig)

        // Ruestungen schuetzen nur gegen physikalischen Schaden
        if ((!spell || (mappingp(spell) && spell[SP_PHYSICAL_ATTACK]))
            && sizeof(filter(dam_type,PHYSICAL_DAMAGE_TYPES)))
        { 
          // Schutz bestimmen, Minimum 1, aber nur wenn P_AC > 0
          // Um Rundungsverluste zu reduzieren, wird P_AC anfangs mit 10000
          // skaliert. Beim runterskalieren wird aufgerundet (Addition von
          // 5000 vor Division).
          int pac = QueryProp(P_AC) * 10000;
          if (pac > 0)
            prot = ((pac/4 + random(pac*3/4 + 1) + 5000)/10000) || 1;
          object stat = find_object("/d/erzmagier/zesstra/pacstat");
          if (stat)
            ({string})stat->acstat(QueryProp(P_ARMOUR_TYPE),prot,
                         random(pac)+1);

          // ruestungschutz an defendfunc weitermelden
          if (mappingp(spell) &&
              mappingp(einfo=spell[EINFO_DEFEND])) {
              // Schutz d. akt. Ruestung vermerken.
              einfo[DEFEND_CUR_ARMOUR_PROT]=prot;
              // daten der Ruestung vermerken.
              if (mappingp(einfo[DEFEND_ARMOURS])) {
                einfo[DEFEND_ARMOURS][ME,DEF_ARMOUR_PROT]=prot;
              }
          } // ende vom if (mapping(spell) ...)
        } // ende vom if (phys Schaden)

    } // ende vom else (wenn kein AT_MISC) 

    // Ist eine DefendFunc gesetzt, wird diese ausgewertet
    if (closurep(defend_cl)) {
        if (!objectp(get_type_info(defend_cl,2))) {
            // Closure gesetzt, aber nicht gueltig, schauen, ob wir sie neu
            // erstellen koennen.
            if (objectp(def_func=QueryProp(P_DEFEND_FUNC))) {
                defend_cl=symbol_function("DefendFunc",def_func);
            }
            // sonst loeschen, um spaeter diesen Zweig ganz zu sparen.
            else defend_cl=0;
        }
        // BTW: Es ist ok, wenn defend_cl jetzt 0 ist, dann liefert funcall()
        // auch 0.
        // Bei Netztoten keine (zurueckschlagende) DefendFunc
        if (objectp(pl=QueryProp(P_WORN)) && (!query_once_interactive(pl) ||
                interactive(pl)) ) {
          // Der Rueckgabewert der DefendFunc wird zum Schutz addiert
          prot += funcall(defend_cl, dam_type, spell, enemy);
          // leider kann die DefendFunc jetzt auch noch das Objekt zerstoert
          // haben...
          if (!objectp(this_object()))
            return prot;
        }
    }

    // Zeitpunkt der letzten Benutzung ausgeben
    SetProp(P_LAST_USE,time());

    // Berechneten Schutz zurueckgeben
    return prot;
}

// Es duerfen nur "legale" Ruestungstypen gesetzt werden, ansonsten
// wird AT_ILLEGAL gesetzt.
static mixed _set_armour_type(mixed type ) {
    if (!({int})COMBAT_MASTER->valid_armour_type(type))
    {
        Set(P_ARMOUR_TYPE, (type=AT_ILLEGAL), F_VALUE);
    }
    else
    {
        Set(P_ARMOUR_TYPE, type);
    }
    AddId(type);

    resistance_strengths=([]);
    return type;
}


// Wird etwas an P_DEFEND_FUNC geaendert, muss die zugehoerige closure
// neu erstellt werden.
static object _set_defend_func(object arg) {
  if (objectp(arg) &&
      closurep(defend_cl=symbol_function("DefendFunc",arg))) {  
    return Set(P_DEFEND_FUNC, arg, F_VALUE);
  }
  defend_cl=0;
  return(Set(P_DEFEND_FUNC, 0, F_VALUE));
}

// Auch Ruestungen koennen einen Schadenstyp haben. Dieser kann als string
// oder array angegeben werden, wird aber intern auf jeden Fall als
// array gespeichert.
static 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);
}

// Ruestungen koennen Resistenzen setzen. Diese werden jedoch nicht wie
// "normale" Resistenzen gesetzt, sondern als Prozentwerte der fuer diesen
// Typ maximal zulaesigen Resistenz. Die Aenderung der Resistenzen darf
// nur durch die Ruestung selbst erfolgen.
// Beispiel: ([DT_FIRE: 100, DT_WATER: -150])
// max. Feuerresistenz, 1.5fache Anfaelligkeit
static mixed _set_resistance_strengths(mixed resmap) {
    float  max_res;
    object worn_by;

    // Es duerfen nur mappings angegeben werden
    if (!mappingp(resmap))
    {
        return -1;
    }

    // die Maxwerte muessen jeweils durch -100 geteilt sein, da hinterher
    // mit der Prozentzahl multipliziert wird und die angabe der Vorzeichen
    // hier umgekehrt wie bei den "normalen" Resistenzen ist. Der
    // Maximalwert ist vom Ruestungstyp abhaengig.
    switch (QueryProp(P_ARMOUR_TYPE))
    {
        case AT_CLOAK  :
        case AT_RING   :
        case AT_AMULET : max_res=-0.0010;
                         break;
        case AT_SHIELD :
        case AT_ARMOUR : max_res=-0.0015;
                         break;
        default        : max_res=-0.0005;
    }

    // Resistenz-Mapping aktualisieren
    resistance_strengths=([]);
    foreach(string damtype, int res: resmap)
    {
        if (!intp(res)) res=to_int(res);
        // Mehr als 100 Prozent ist nicht erlaubt
        if (res>100)
        {
            res=100;
        }
        else if (res<0)
        {
             res=(res/4)*5;
             // Man kann auch nicht beliebig negativ werden
             if (res<-1000)
             {
                 res=-1000;
             }
        }
        // Der Resistenzwert berechnet sich aus dem Produkt des
        // Maximalwertes und der Prozentzahl
        resistance_strengths[damtype]=res*max_res;
    }

    // Werden die Resistenzen bei einer getragenen Ruestung geaendert,
    // muss der Traeger davon natuerlich beeinflusst werden.
    if (objectp(worn_by=QueryProp(P_WORN)))
    {
        ({int})worn_by->AddResistanceModifier(resistance_strengths,
                                       QueryProp(P_ARMOUR_TYPE));
    }
   return resistance_strengths;
}

// Bei einem QueryProp(P_RESISTANCE_STRENGTHS) soll das aktuelle
// Resistenzen-Mapping zurueckgegeben werden
static mapping _query_resistance_strengths() {
  return (resistance_strengths||([]));
}

