// MorgenGrauen MUDlib
//
// living/attributes.c -- attributes for living objects
//
// $Id: attributes.c 8375 2013-02-12 21:52:58Z Zesstra $

#include <sys_debug.h>

// attribute handling
//
//   filter_ldfied: str, dex, con, int
//
// In den Attributen und Abilites werden Rassenspzifische und erworbene
// Faehigkeiten (mit autoload-Eigenschaft) abgepseichert.
//
// Funktionen:
//   SetAttribute( attr, val ) (Erzeuge und) setze das Attribut auf val.
//   QueryAttribute( attr )    Gebe den Wert des Attributes zurueck.
//
//   Wenn ein Objekt eine Funktion _filterattr_<name> beitzt, wird beim Setzen
//   des Attributes <name>, der vorgeschlagene Wert uebergeben und der von
//   dieser Funktion zurueckgegebene gesetzt. (fuer ueberpruefungszwecke)
//   Gleiches gilt fuer _filterabil_<name>.

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

#define NEED_PROTOTYPES
#include <thing/properties.h>
#include <attributes.h>
#include <player/gmcp.h>
#undef NEED_PROTOTYPES

#include <config.h>
#include <properties.h>

mapping attributes; // Dies sind die mit ZTs veraenderbaren Attribute
mapping attributes_modifier; // Modifier sollen gespeichert werden
nosave mixed* attributes_timed_mods; //P_TIMED_ATTR_MOD
nosave mapping attributes_offsets; // Offsets NICHT speichern!
nosave mapping used_attributes_offsets; // Zur Beschleunigung der Berechnung
nosave object* all_modifiers; // objekte mit P_X/M_ATTR_MOD, P_X/M_HEALTH_MOD
nosave object* invalid_modifiers; // objekte welche das limit ueberschreiten
nosave int cumulative_mod; // bilanz der P_X/M_ATTR_MOD
nosave int hp_off;
nosave int sp_off;


nomask public int SetTimedAttrModifier(string key, mapping modifier, 
    int outdated, object dependent, mixed notify) {
  if(!key || key=="" || !modifier || (outdated>0 && outdated<time()) || 
      (notify && !stringp(notify) && !objectp(notify)) ) {
    return TATTR_INVALID_ARGS;
  }
  
  
  if(member(attributes_timed_mods[TATTR_ENTRIES],key)) {
    // change entry
    attributes_timed_mods[TATTR_ENTRIES][key,TATTR_MOD]=modifier;
    attributes_timed_mods[TATTR_ENTRIES][key,TATTR_OUTDATED]=outdated;
    attributes_timed_mods[TATTR_ENTRIES][key,TATTR_DEPENDENT]=dependent;
    attributes_timed_mods[TATTR_ENTRIES][key,TATTR_NOTIFY]=notify;
  }
  else {
    // add entry
    attributes_timed_mods[TATTR_ENTRIES]+=([key:modifier;outdated;dependent;notify]);
  }
  
  // add outdate
  if(outdated>0 && member(attributes_timed_mods[TATTR_OUTDATE],outdated)==-1)
  {
    attributes_timed_mods[TATTR_OUTDATE]+=({outdated});
    attributes_timed_mods[TATTR_OUTDATE]=
      sort_array(attributes_timed_mods[TATTR_OUTDATE],#'<);
  }
  
  // add dependent
  if(objectp(dependent))
  {
  	if(member(attributes_timed_mods[TATTR_DEPENDENTS],key))
  	{
	  attributes_timed_mods[TATTR_DEPENDENTS][key]=dependent;
  	}
  	else
  	{
          attributes_timed_mods[TATTR_DEPENDENTS]+=([key:dependent]);
  	}
  }
  else
  {
  	// remove previously set dependent
  	if(member(attributes_timed_mods[TATTR_DEPENDENTS],key))
  	{
	  attributes_timed_mods[TATTR_DEPENDENTS]-=([key]);
  	}
  }
  
  UpdateAttributes();

  return TATTR_OK;
}

nomask public mapping QueryTimedAttrModifier(string key)
{
  int outdated;
  object dependent;
  mixed notify;
  mapping mod;
  
  if(!key || key=="")
  {
    return ([]);
  }

  if(!member(attributes_timed_mods[TATTR_ENTRIES],key))
  { 
    return ([]);
  }

  mod=deep_copy(attributes_timed_mods[TATTR_ENTRIES][key,TATTR_MOD]);
  outdated=attributes_timed_mods[TATTR_ENTRIES][key,TATTR_OUTDATED];
  dependent=attributes_timed_mods[TATTR_ENTRIES][key,TATTR_DEPENDENT];
  notify=attributes_timed_mods[TATTR_ENTRIES][key,TATTR_NOTIFY];
  
  return ([key:mod;outdated;dependent;notify ]);
}

nomask public int DeleteTimedAttrModifier(string key)
{
  if(!key || key=="")
  {
    return TATTR_INVALID_ARGS;
  }

  if(!member(attributes_timed_mods[TATTR_ENTRIES],key))
  { 
    return TATTR_NO_SUCH_MODIFIER;
  }
  
  attributes_timed_mods[TATTR_DEPENDENTS]-=([key]);
  attributes_timed_mods[TATTR_ENTRIES]-=([key]);
  UpdateAttributes();
  
  return TATTR_OK;
}

nomask protected void attribute_hb()
{
  int now,i,k,outdated;
  string* keys;
  mapping tonotify;
	
  // initialize
  now=time();
  tonotify=([]);

  keys=m_indices(attributes_timed_mods[TATTR_ENTRIES]);
  
  // delete outdated 
  for(i=sizeof(attributes_timed_mods[TATTR_OUTDATE])-1;i>=0;i--)
  {
  	outdated=attributes_timed_mods[TATTR_OUTDATE][i];
  	if(outdated>now)
  	{
  	  break;
  	}
  	
  	for(k=sizeof(keys)-1;k>=0;k--)
  	{
  	  if(attributes_timed_mods[TATTR_ENTRIES][keys[k],TATTR_OUTDATED]==outdated)
  	  {
  	    // bei fehlendem notifier wurde das zum verhaengnis
  	    // dank an gloinson
  	    /*
  	    if(objectp(attributes_timed_mods[TATTR_ENTRIES][keys[k],TATTR_NOTIFY]))
  	    {
  	    */
  	    tonotify+=([keys[k]:attributes_timed_mods[TATTR_ENTRIES][keys[k],TATTR_NOTIFY]]);
  	    //}
  	    
	    attributes_timed_mods[TATTR_DEPENDENTS]-=([keys[k]]);
 	    attributes_timed_mods[TATTR_ENTRIES]-=([keys[k]]);
  	    keys-=({keys[k]});
  	  }
  	}
  	
  	attributes_timed_mods[TATTR_OUTDATE]-=({outdated});
  }
  
  // delete depending
  keys=m_indices(attributes_timed_mods[TATTR_DEPENDENTS]);
  for(i=sizeof(keys)-1;i>=0;i--)
  {
  	if(!objectp(attributes_timed_mods[TATTR_DEPENDENTS][keys[i]]))
  	{
  	    // siehe oben
  	    /*
  	    if(objectp(attributes_timed_mods[TATTR_ENTRIES][keys[i],TATTR_NOTIFY]))
  	    {
  	    */
  	    tonotify+=([keys[i]:attributes_timed_mods[TATTR_ENTRIES][keys[i],TATTR_NOTIFY]]);
  	    //}

	    attributes_timed_mods[TATTR_DEPENDENTS]-=([keys[i]]);
 	    attributes_timed_mods[TATTR_ENTRIES]-=([keys[i]]);
  	    keys-=({keys[i]});
  	}
  }
  
  
  // update
  if(sizeof(tonotify))
  {
    UpdateAttributes();
    call_out(#'notifyExpiredModifiers,0,tonotify);
  }
}

nomask protected void notifyExpiredModifiers(mapping nots)
{
  int i;
  string* keys;
  while(remove_call_out(#'notifyExpiredModifiers)!=-1);
  
  if(!nots)
  {
    return;
  }
  
  keys=m_indices(nots);
  for(i=sizeof(nots)-1;i>=0;i--)
  {
  	if(nots[keys[i]] && 
	    ( objectp(nots[keys[i]])||stringp(nots[keys[i]]) ) )
  	{
  	   call_other(nots[keys[i]],"NotifyTimedAttrModExpired",keys[i]);
  	}
  }
}


// invalide modifier benachrichtigen
nomask protected void notifyInvalidModifiers() {

  while(remove_call_out(#'notifyInvalidModifiers)!=-1);
  
  if(!invalid_modifiers) {
    invalid_modifiers=({});
  }
  
  call_other(invalid_modifiers,"NotifyXMAttrModLimitViolation");

}


// welche Modifier / modif. Objekte wirken nun?
protected nomask void calculate_valid_modifiers() {
  closure qp;
  mapping res;	
  string key;	
  int wert;
  // Unterscheidung Bonus <-> Malus, weil der Malus voll eingehen soll	
  int hp_malus, sp_malus;
 
  used_attributes_offsets=([]);
  cumulative_mod=0;
  hp_off=sp_off=0;
  invalid_modifiers=({});

  // rassenspezifische boni P_ATTRIBUTES_OFFSETS  
  if ( mappingp(attributes_offsets) )
    used_attributes_offsets+=attributes_offsets;

  if (!pointerp(all_modifiers) || !sizeof(all_modifiers)) {
    // in diesem Fall koennen wir hier direkt mit dieser Funktion Schluss
    // machen. ;-)
    return;
  }
  else
    all_modifiers-=({0}); //zerstoerte Objekte rauswerfen.
    
  // einmal ueber alle modifizierenden Objekt iterieren und aufaddieren
  foreach(object ob: all_modifiers) {
    qp = symbol_function("QueryProp",ob);
 
    if (!objectp(ob) || environment(ob)!=this_object()) {
      all_modifiers-=({ob});
      continue;
    }
 		
    // ext. Attribut-Modifier
    if ( mappingp(res=funcall(qp,P_X_ATTR_MOD)) ) {		
      foreach(key, wert: res) {
        cumulative_mod+=wert;
      }
    }

    // magic Attribut-Modifier
    if ( mappingp(res=funcall(qp,P_M_ATTR_MOD))
        && ( funcall(qp,P_WORN)
            || funcall(qp,P_WIELDED) ) ) {		
      foreach(key, wert: res) {
        cumulative_mod+=wert;
      }
    }
    // Magic Health-Modifier 		
    if ( mappingp(res=funcall(qp,P_M_HEALTH_MOD))
        && ( funcall(qp,P_WORN)
            || funcall(qp,P_WIELDED) ) ) {
      if (res[P_HP] < 0)
        hp_malus += res[P_HP];
      else
        hp_off+=res[P_HP];

      if (res[P_SP] < 0)
        sp_malus += res[P_SP];
      else
        sp_off+=res[P_SP];
      }
	      
    // external Health Modifier
    if ( mappingp(res=funcall(qp,P_X_HEALTH_MOD)) ) {
      if (res[P_HP] < 0)
        hp_malus += res[P_HP];
      else
        hp_off+=res[P_HP];

      if (res[P_SP] < 0)
        sp_malus += res[P_SP];
      else
        sp_off+=res[P_SP];	    
    }	
  
  } // Ende 1. foreach()
  
 
  // und nochmal, soviele Objekt wieder rausschmeissen, bis das Limit wieder
  // unterschritten wird. (Verbesserungsvorschlaege erwuenscht.) :-(
  foreach(object ob: all_modifiers) {

    qp = symbol_function("QueryProp",ob);
 
    if ( mappingp(res=funcall(qp,P_X_ATTR_MOD)) ) {
      if(cumulative_mod>CUMULATIVE_ATTR_LIMIT) { 
        invalid_modifiers+=({ob});	  
	foreach(key, wert: res) {
          cumulative_mod-=wert;
        }
      }
      else {
        add_offsets(res);
      }
    }

    if ( mappingp(res=funcall(qp,P_M_ATTR_MOD))
        && ( funcall(qp,P_WORN)
            || funcall(qp,P_WIELDED) ) ) {
      if(cumulative_mod>CUMULATIVE_ATTR_LIMIT) {     
        if(member(invalid_modifiers,ob)==-1) {
          invalid_modifiers+=({ob});
        }			
	foreach(key, wert: res) {
          cumulative_mod-=wert;
        }
      }
      else {
        add_offsets(res);
      }
    }
  }

  // HEALTH_MOD werden durch eine Formel 'entschaerft', damit man nur schwer
  // das Maximum von 150 erreichen kann. (Formel von Humni, beschlossen auf 3.
  // EM-Treffen)
  // Mali gehen aber voll ein
  hp_off = (int)(150 - (150*150.0/(150 + hp_off))) + hp_malus;
  sp_off = (int)(150 - (150*150.0/(150 + sp_off))) + sp_malus;

  /* alte Version
    hp_off += hp_malus;
    sp_off += sp_malus;
  */
 
  // notify invalid modifiers
  if(sizeof(invalid_modifiers)>0) {
    call_out(#'notifyInvalidModifiers,0);
  }
}

// abmelden eines modifiers 
nomask public void deregister_modifier(object modifier)
{ 
  if (!pointerp(all_modifiers)) {
    return;
  }

  // valid object?
  if (!objectp(modifier) || member(all_modifiers,modifier)==-1) {
    return;
  }
  
  all_modifiers-=({modifier});
  if (invalid_modifiers) {
    invalid_modifiers-=({modifier});
  }
}

// anmelden eines modifiers 
nomask public void register_modifier(object modifier) { 
  closure qp;
  
  if (!pointerp(all_modifiers)) {
    all_modifiers=({});
  }

  // valid object?
  if (!objectp(modifier) || environment(modifier)!=this_object() || 
      member(all_modifiers,modifier)!=-1) {
    return;
  }
  
  qp = symbol_function("QueryProp",modifier);
  // modifier after all? Die P_M_* muessen getragen/gezueckt sein.
  if(mappingp(funcall(qp,P_X_ATTR_MOD)) ||
     mappingp(funcall(qp,P_X_HEALTH_MOD)) ||
    ((mappingp(funcall(qp,P_M_ATTR_MOD)) ||
       mappingp(funcall(qp,P_M_HEALTH_MOD))) &&
      (funcall(qp,P_WORN) || funcall(qp,P_WIELDED)) ) ) {
    all_modifiers+=({modifier});
  }
}

protected void add_offsets(mapping arr) {
  if ( !mappingp(arr) )
    return;

  foreach(string key, int wert: arr) {
    used_attributes_offsets[key]+=wert;
  }
}

public void UpdateAttributes() {
  mixed   *ind;
  int     i;
  
  // alle gueltigen Modifier ermitteln aus Objekten im Inventar.
  calculate_valid_modifiers();

  // persistente modifier drauf (frosch zb)
  // aus P_ATTRIBUTES_MODIFIERS
  if ( mappingp(attributes_modifier) ) {
    foreach(mixed key, mapping wert: attributes_modifier) {
      add_offsets(wert); // Modifier addieren...		
    }
  }
  // timed modifier drauf aus P_TIMED_ATTR_MOD
  ind=m_indices(attributes_timed_mods[TATTR_ENTRIES]);
  for ( i=sizeof(ind)-1 ; i>=0 ; i-- ) {
    // Modifier addieren...
    add_offsets(attributes_timed_mods[TATTR_ENTRIES][ind[i],0]);
  }
  // Bei Monstern werden die HP/SP ueblicherweise selbst gesetzt
  if ( !query_once_interactive(this_object()))
    return;

  SetProp(P_MAX_HP, QueryAttribute(A_CON)*8+42+hp_off);
  SetProp(P_MAX_SP, QueryAttribute(A_INT)*8+42+sp_off);
  
  if(QueryProp(P_HP)>QueryProp(P_MAX_HP)) {
    SetProp(P_HP,QueryProp(P_MAX_HP));
  }
  
  if(QueryProp(P_SP)>QueryProp(P_MAX_SP)) {
    SetProp(P_SP,QueryProp(P_MAX_SP));
  }

  GMCP_Char( ([ A_INT: QueryAttribute(A_INT),
                A_DEX: QueryAttribute(A_DEX),
                A_STR: QueryAttribute(A_STR),
                A_CON: QueryAttribute(A_CON) ]) );
}


protected void create() {
  hp_off=sp_off=0;
  used_attributes_offsets=([]);
  all_modifiers=({});
  invalid_modifiers=({});
  cumulative_mod=0;
  
  Set(P_ATTRIBUTES_MODIFIER, attributes_modifier=([])); // nicht geschuetzt
  Set(P_ATTRIBUTES_OFFSETS, attributes_offsets=([]));
  Set(P_ATTRIBUTES_OFFSETS, PROTECTED, F_MODE);
  Set(P_ATTRIBUTES, attributes=([]));
  Set(P_ATTRIBUTES, PROTECTED, F_MODE);

  Set(P_TIMED_ATTR_MOD, attributes_timed_mods=({ ({}),([]),([]) }));
  Set(P_TIMED_ATTR_MOD, NOSETMETHOD|SECURED, F_MODE_AS);
}

static mixed _query_timed_attr_mod() {
  return Set(P_TIMED_ATTR_MOD,	    
      ({attributes_timed_mods[0],
	deep_copy(attributes_timed_mods[1]),
	deep_copy(attributes_timed_mods[2])}));
}

static mapping _set_attributes(mapping arr) 
{
  Set(P_ATTRIBUTES, attributes=arr);
  UpdateAttributes();
  return arr;
}

static mapping _query_attributes() 
{
  return deep_copy(Set(P_ATTRIBUTES, attributes)); 
}

static mapping _set_attributes_offsets(mapping arr) 
{
  Set(P_ATTRIBUTES_OFFSETS, attributes_offsets=arr);
  UpdateAttributes();
  return attributes_offsets;
}

static mapping _query_attributes_offsets() 
{ 
  return deep_copy(Set(P_ATTRIBUTES_OFFSETS, attributes_offsets));
}

static mixed _set_attributes_modifier(mixed arr) 
{ string fn;
  mixed pre;
  mapping map_ldfied;
  
  if ( pointerp(arr) && (sizeof(arr)>=2) )
  {
    pre=arr[0];
    map_ldfied=arr[1];
  }
  else 
  {
    pre=previous_object();
    map_ldfied=arr;
  }

  if ( objectp(pre) )
    fn=old_explode(object_name(pre),"#")[0];
  else
    fn=pre;

  if ( !stringp(fn) )
    return 0;

  // wenn Modifier kein mapping oder ein leeres Mapping: loeschen
  if ( !mappingp(map_ldfied) || !sizeof(map_ldfied))
    m_delete(attributes_modifier,fn);
  else
    attributes_modifier[fn]=map_ldfied;

  Set(P_ATTRIBUTES_MODIFIER, attributes_modifier);
  UpdateAttributes();
  return attributes_modifier[fn];
}

static mapping _query_attributes_modifier() 
{
  return deep_copy(attributes_modifier);  
}

public int SetAttr(string attr, int val) 
{ closure filter_ldfied;

  if ( filter_ldfied = symbol_function("_filterattr_"+attr, this_object()) ) 
    val = funcall(filter_ldfied, val );

  attributes[attr] = val;
  UpdateAttributes();
  return val;
}

public int SetAttribute(string attr, int val) 
{
  return SetAttr(attr, val-used_attributes_offsets[attr]);
}

// Diese Funktion sollte zum Abfragen verwendet werden:
public int QueryAttribute(string attr) 
{ int re;

  re=attributes[attr]+used_attributes_offsets[attr];

  if ( query_once_interactive(this_object()) && (re>30) )
    re=30;

  return re;
}

public int QueryRealAttribute(string attr) 
{
  return attributes[attr];
}

public int SetRealAttribute(string attr, int val) 
{
  return SetAttr(attr, val);
}

public int QueryAttributeOffset(string attr) 
{
  return used_attributes_offsets[attr];
}

public status TestLimitViolation(mapping check)
{
  int k,test;
  mixed* ind;
    
  if(!check || !mappingp(check))
  {
    return 0;
  }

  test=0;
  ind=m_indices(check);
  for( k=sizeof(ind)-1 ; k>=0 ; k-- )
  {
    test+=check[ind[k]];
  }
  
  test+=cumulative_mod;
  if(test>CUMULATIVE_ATTR_LIMIT)
  {
    return 1;
  }
  
  return 0;
}

/*
 *------------------------------------------------------------
 * attributes compatibility functions
 */

protected int _filterattr_str(int val)
{
  return ( (val<0) ? 0 : (val>20) ? 20 : val );
}

protected int _filterattr_dex(int val)
{
  return ( (val<0) ? 0 : (val>20) ? 20 : val );
}

protected int _filterattr_int(int val)
{
  return ( (val<0) ? 0 : (val>20) ? 20 : val );
}

protected int _filterattr_con(int val)
{
  return ( (val<0) ? 0 : (val>20) ? 20 : val );
}
