blob: 3d7cb797f3fde934f80f952005455c5c617784a6 [file] [log] [blame]
// MorgenGrauen MUDlib
//
// lepmaster.c -- Master, welcher aus scoremaster, explorationmaster,
// questmaster und dem Spielerobjekt Informationen
// ausliest und aus diesen die Levelpunkte des Spieler
// berechnet
// Weiters derjenige, der die Seheranforderungen
// prueft.
//
// $Id: lepmaster.c 9168 2015-03-05 00:04:22Z Zesstra $
// Hier kommen Funktionen fuer die Levelpunkte
#pragma strict_types
#pragma no_clone
#pragma no_shadow
#pragma no_inherit
#pragma verbose_errors
#pragma combine_strings
//#pragma pedantic
//#pragma range_check
#pragma warn_deprecated
#include <config.h>
#include <properties.h>
#include <new_skills.h>
#include <exploration.h>
#include <questmaster.h>
#include <scoremaster.h>
#include <wizlevels.h>
#include "lepmaster.h"
// Das Programm zur Foerderung der kleinen Level aktivieren. ;-)
#define __PFOERKL__ 1
// die ersten 8 Level, d.h. Level 1 bis 8 entsprechen diesen LEPs.
int *LOW_LEVEL_LEP_LIST = ({100,120,140,180,220,300,360,420}); // 9. Level: 500 LEP
#define REQ_TEXT1 ([0:"unglaublich viel", \
1:"unglaublich viel", \
2:"enorm viel", \
3:"sehr viel", \
4:"viel", \
5:"einiges", \
6:"etwas", \
7:"wenig", \
8:"sehr wenig", \
9:"kaum etwas" ])
#define REQ_TEXT2 ([0:"unglaublich viele", \
1:"unglaublich viele", \
2:"enorm viele", \
3:"sehr viele", \
4:"viele", \
5:"einige", \
6:"ein paar", \
7:"wenige", \
8:"sehr wenige", \
9:"kaum" ])
#define DEBUG(x,y)
//#define DEBUG(x,y) if (find_player("zook")) tell_object(find_player("zook"),sprintf(x,y))
void create()
{
seteuid(getuid());
}
int QueryLEPForPlayer(object pl)
{
int ret, val, i, l;
if (extern_call() && !IS_ARCH(geteuid(previous_object())))
return -1;
if (!pl || !query_once_interactive(pl))
return -2;
// Grundoffset 100, da man mit Level 1 statt 0 startet
ret = 100;
// Beitrag A: Stupse von NPC-Erstkills
ret += (int)SCOREMASTER->QueryKillPoints(pl);
DEBUG("Nach KP: ret = %d\n", ret);
// Beitrag B: Stupse von geloesten Miniquests
ret += (int)QM->QueryMiniQuestPoints(pl);
DEBUG("Nach MQP: ret = %d\n", ret);
// Beitrag C: Questpunkte
// werden 1:1 uebernommen;
ret += (int)pl->QueryProp(P_QP);
DEBUG("Nach QP: ret = %d\n", ret);
// Beitrag D: Erfahrungspunkte
// Stupse = XPs ^ 0.32
val = (int)pl->QueryProp(P_XP);
if (val<1) l=0;
else l=to_int(exp(log(to_float(val))*0.32));
ret += l;
DEBUG("Nach XP: ret = %d\n", ret);
// Beitrag E: Zaubertraenke
// Gefundene Traenke geben 5 LEP
// Die Heiltraenke geben zusaetzlich 10+20+30+40 LEP
i = 80 - (val = sizeof((int *)pl->QueryProp(P_POTIONROOMS)));
ret += 5*i + ([ 0: 100, 1: 60, 2: 30, 3: 10])[val];
// Beitrag F: Forscherpunkte
// Pro FP gibt es 6 Stufenpunkte
ret += 6 * (int)EPMASTER->QueryExplorationPoints(pl);
DEBUG("Nach FP: ret = %d\n", ret);
// Beitrag G: Gildeneinstufung
// Maximale Gildeneinstufung (10000) entspricht vier Leveln
ret += ((int)pl->QueryProp(P_GUILD_RATING))/25;
DEBUG("Nach GR: ret = %d\n", ret);
// Ausgabe gibt es nur in 20er-Schritten
ret -= ret%20;
return (ret > 100) ? ret : 100;
}
nomask int QueryLEP()
{
if (!previous_object())
return 0;
return QueryLEPForPlayer(previous_object());
}
nomask int QueryLevel(int lep) {
if (lep<=0)
lep=QueryLEP();
if (lep<=0)
return 0;
#ifdef __PFOERKL__
// normale Level alle 100 LEP
if (lep >= 500)
return lep/100 + 4;
else {
// level mit weniger LEP am Anfang (1-8)
// Level aus der LOW_LEVEL_LEP_LIST raussuchen.
int lev = sizeof(LOW_LEVEL_LEP_LIST) - 1;
for ( ; lev >= 0; --lev) {
if (LOW_LEVEL_LEP_LIST[lev] <= lep)
break; // gefunden
}
return lev+1;
}
#else
return lep/100;
#endif // __PFOERKL__
return 0;
}
// Wieviele LEP fehlen zum naechsten Level?
nomask int QueryNextLevelLEP(int lvl, int lep) {
int needed;
if (QueryLevel(lep) > lvl)
return 0;
#ifdef __PFOERKL__
if (lvl < sizeof(LOW_LEVEL_LEP_LIST))
needed = LOW_LEVEL_LEP_LIST[lvl];
else
needed = (lvl-3) * 100; // (lvl + 1 - 4) * 100
#else
needed = (lvl+1) * 100;
#endif // __PFOERKL__
// needed sind jetzt die insgesamt benoetigten LEP. Vorhandene abziehen.
needed -= lep;
// nix < 0 zurueckliefern
return max(needed,0);
}
string QueryForschung()
{
int max, my, avg;
string ret;
if ((my=(int)EPMASTER->QueryExplorationPoints(getuid(previous_object()))) < MIN_EP)
return "Du kennst Dich im "MUDNAME" so gut wie gar nicht aus.\n";
my *= 100;
max = my/(int)EPMASTER->QueryMaxEP();
avg = my/(int)EPMASTER->QueryAverage();
ret = "Verglichen mit Deinen Mitspielern, kennst Du Dich im "MUDNAME" ";
switch(avg) {
case 0..10:
ret += "kaum";
break;
case 11..40:
ret += "aeusserst schlecht";
break;
case 41..56:
ret += "sehr schlecht";
break;
case 57..72:
ret += "schlecht";
break;
case 73..93:
ret += "unterdurchschnittlich";
break;
case 94..109:
ret += "durchschnittlich gut";
break;
case 110..125:
ret += "besser als der Durchschnitt";
break;
case 126..145:
ret += "recht gut";
break;
case 146..170:
ret += "ziemlich gut";
break;
case 171..210:
ret += "gut";
break;
case 211..300:
ret += "sehr gut";
break;
case 301..400:
ret += "ausserordentlich gut";
break;
case 401..500:
ret += "unheimlich gut";
break;
default:
ret += "einfach hervorragend";
break;
}
ret += " aus.\nAbsolut gesehen ";
switch(max) {
case 0..5:
ret += "kennst Du nur wenig vom "MUDNAME".";
break;
case 6..10:
ret += "solltest Du Dich vielleicht noch genauer umsehen.";
break;
case 11..17:
ret += "bist Du durchaus schon herumgekommen.";
break;
case 18..25:
ret += "hast Du schon einiges gesehen.";
break;
case 26..35:
ret += "bist Du schon weit herumgekommen.";
break;
case 36..50:
ret += "koenntest Du eigentlich einen Reisefuehrer herausbringen.";
break;
case 51..75:
ret += "hast Du schon sehr viel gesehen.";
break;
default:
ret += "besitzt Du eine hervorragende Ortskenntnis.";
}
return break_string(ret, 78, 0, 1);
}
nomask mixed QueryWizardRequirements(object player)
{
// Diese Funktion gibt ein 2-elementiges Array zurueck, in dem im ersten
// Element steht, ob der Spieler Seher werden kann (1) oder
// nicht (0) und im zweiten Element steht, was genau ihm noch
// fehlt.
// Fehlercode ist ({-1, ""})
// Die Umrechnungsfaktoren wurden einfach aus QueryLEP uebernommen; ggf.
// kann man das einmal in Unterfunktionen auslagern.
mixed ret;
string s;
int i,z,val;
ret = ({-1, "Hier ist etwas schief gelaufen. Bitte einen Erzmagier\n"
+"benachrichtigen.\n"});
s = "";
i = 0;
if(!player || !objectp(player))
player=(this_player()?this_player():this_interactive());
if(!player)
return ({-1,""});
DEBUG("Es geht um: %O\n", player);
// Abenteuerpunkte
DEBUG("Abenteuerpunkte: %d ("+REQ_QP+")\n", player->QueryProp(P_QP));
if (player->QueryProp(P_QP) < REQ_QP) {
s += sprintf(" * Dir fehlen noch mindestens %d Abenteuerpunkte.\n",
REQ_QP - (int)player->QueryProp(P_QP));
i--;
}
// Forscherpunkte
z = 6 * (int)EPMASTER->QueryExplorationPoints(player);
DEBUG("Forscherpunkte: %d ("+REQ_EP+")\n", z);
if (z < REQ_EP) {
s += sprintf(" * Du kennst Dich im "MUDNAME" noch nicht genug aus, "
+"genau genommen\n musst Du Dir noch %s ansehen.\n",
REQ_TEXT1[(z*10/REQ_EP)] );
i--;
}
// Zaubertraenke
z = 80 - (val = sizeof((int*)player->QueryProp(P_POTIONROOMS)));
z = z*5 + ([0:100, 1:60, 2:30, 3:10])[val];
DEBUG("Zaubertraenke: %d ("+REQ_P+")\n", z);
if (z < REQ_P) {
s += sprintf(" * Du musst noch einige Zaubertraenke (ca. %d) suchen.\n",
(REQ_P - z)/5 );
i--;
}
// Erstkills
z = (int)SCOREMASTER->QueryKillPoints(player);
DEBUG("Erstkills: %d ("+REQ_K+")\n", z);
if (z < REQ_K) {
s += sprintf(" * Du hast noch nicht genuegend wuerdige Gegner erlegt, genau "
+"genommen\n musst Du noch %s wuerdige Monster toeten.\n",
REQ_TEXT2[(z*10/REQ_K)] );;
i--;
}
int minlevel = QueryLevel(REQ_LEP);
// Restliche Stufenpunkte
DEBUG("Stufenpunkte: %d ("+REQ_LEP+")\n", player->QueryProp(P_LEP));
if ((int)(player->QueryProp(P_LEP)) < REQ_LEP) {
s += sprintf(" * Du musst mindestens %d Stufenpunkte, entspricht Stufe %d, "
"erreichen.\n", REQ_LEP, minlevel);
i--;
}
// Demnach mindestens REQ/100-Level
DEBUG("Level: %d ("+REQ_LEP/100+")\n", player->QueryProp(P_LEVEL));
if ((int)player->QueryProp(P_LEVEL) < minlevel) {
s += sprintf(" * Du musst mindestens Stufe %d erreichen.\n", minlevel);
i--;
}
if(i<0) {
ret = ({-1,
sprintf("Du hast noch nicht alle Seher-Anforderungen erfuellt.\n"
+"Im einzelnen fehlt Dir folgendes:\n\n%s\n"
+break_string("Falls Du Dir nun dennoch unsicher bist, "
+"welche Anforderungen Du erfuellen musst, dann "
+"schaue bei 'hilfe seher' und 'hilfe stufenpunkte' doch einfach noch "
+"einmal nach. Sind dann "
+"immer noch Dinge offen oder unklar, so sprich einfach einen "
+"der Erzmagier an.", 78,0,1),s) });
}
if (i==0) {
ret = ({1, break_string(
"Du hast alle Seher-Anforderungen erfuellt. Wende Dich doch "
+"einmal an Merlin und frage ihn, ob er Dich befoerdert.",
78,0,1) });
}
return ret;
}
nomask int QueryReadyForWiz(object player)
{
mixed r;
r = QueryWizardRequirements(player);
if (!pointerp(r) && sizeof(r)!=2 && !intp(r[0]))
return -1;
return r[0];
}
nomask string QueryReadyForWizText(object player)
{
mixed r;
r = QueryWizardRequirements(player);
if (!pointerp(r) && sizeof(r)!=2 && !stringp(r[1]))
return "Hier ist etwas schief gegangen, bitte verstaendige einen "
+"Erzmagier.";
return r[1];
}