MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // MorgenGrauen MUDlib |
| 2 | // |
| 3 | // lepmaster.c -- Master, welcher aus scoremaster, explorationmaster, |
| 4 | // questmaster und dem Spielerobjekt Informationen |
| 5 | // ausliest und aus diesen die Levelpunkte des Spieler |
| 6 | // berechnet |
| 7 | // Weiters derjenige, der die Seheranforderungen |
| 8 | // prueft. |
| 9 | // |
| 10 | // $Id: lepmaster.c 9168 2015-03-05 00:04:22Z Zesstra $ |
| 11 | |
| 12 | // Hier kommen Funktionen fuer die Levelpunkte |
| 13 | #pragma strict_types |
| 14 | #pragma no_clone |
| 15 | #pragma no_shadow |
| 16 | #pragma no_inherit |
| 17 | #pragma verbose_errors |
| 18 | #pragma combine_strings |
| 19 | //#pragma pedantic |
| 20 | //#pragma range_check |
| 21 | #pragma warn_deprecated |
| 22 | |
| 23 | #include <config.h> |
| 24 | #include <properties.h> |
| 25 | #include <new_skills.h> |
| 26 | #include <exploration.h> |
| 27 | #include <questmaster.h> |
| 28 | #include <scoremaster.h> |
| 29 | #include <wizlevels.h> |
| 30 | |
| 31 | #include "lepmaster.h" |
| 32 | |
| 33 | // Das Programm zur Foerderung der kleinen Level aktivieren. ;-) |
| 34 | #define __PFOERKL__ 1 |
| 35 | |
| 36 | // die ersten 8 Level, d.h. Level 1 bis 8 entsprechen diesen LEPs. |
| 37 | int *LOW_LEVEL_LEP_LIST = ({100,120,140,180,220,300,360,420}); // 9. Level: 500 LEP |
| 38 | |
| 39 | #define REQ_TEXT1 ([0:"unglaublich viel", \ |
| 40 | 1:"unglaublich viel", \ |
| 41 | 2:"enorm viel", \ |
| 42 | 3:"sehr viel", \ |
| 43 | 4:"viel", \ |
| 44 | 5:"einiges", \ |
| 45 | 6:"etwas", \ |
| 46 | 7:"wenig", \ |
| 47 | 8:"sehr wenig", \ |
| 48 | 9:"kaum etwas" ]) |
| 49 | |
| 50 | #define REQ_TEXT2 ([0:"unglaublich viele", \ |
| 51 | 1:"unglaublich viele", \ |
| 52 | 2:"enorm viele", \ |
| 53 | 3:"sehr viele", \ |
| 54 | 4:"viele", \ |
| 55 | 5:"einige", \ |
| 56 | 6:"ein paar", \ |
| 57 | 7:"wenige", \ |
| 58 | 8:"sehr wenige", \ |
| 59 | 9:"kaum" ]) |
| 60 | |
| 61 | #define DEBUG(x,y) |
| 62 | //#define DEBUG(x,y) if (find_player("zook")) tell_object(find_player("zook"),sprintf(x,y)) |
| 63 | |
| 64 | |
| 65 | void create() |
| 66 | { |
| 67 | seteuid(getuid()); |
| 68 | } |
| 69 | |
| 70 | int QueryLEPForPlayer(object pl) |
| 71 | { |
| 72 | int ret, val, i, l; |
| 73 | |
| 74 | if (extern_call() && !IS_ARCH(geteuid(previous_object()))) |
| 75 | return -1; |
| 76 | if (!pl || !query_once_interactive(pl)) |
| 77 | return -2; |
| 78 | |
| 79 | // Grundoffset 100, da man mit Level 1 statt 0 startet |
| 80 | ret = 100; |
| 81 | |
| 82 | // Beitrag A: Stupse von NPC-Erstkills |
| 83 | ret += (int)SCOREMASTER->QueryKillPoints(pl); |
| 84 | |
| 85 | DEBUG("Nach KP: ret = %d\n", ret); |
| 86 | |
| 87 | // Beitrag B: Stupse von geloesten Miniquests |
| 88 | ret += (int)QM->QueryMiniQuestPoints(pl); |
| 89 | |
| 90 | DEBUG("Nach MQP: ret = %d\n", ret); |
| 91 | |
| 92 | // Beitrag C: Questpunkte |
| 93 | // werden 1:1 uebernommen; |
| 94 | ret += (int)pl->QueryProp(P_QP); |
| 95 | |
| 96 | DEBUG("Nach QP: ret = %d\n", ret); |
| 97 | |
| 98 | // Beitrag D: Erfahrungspunkte |
| 99 | // Stupse = XPs ^ 0.32 |
| 100 | val = (int)pl->QueryProp(P_XP); |
| 101 | |
| 102 | if (val<1) l=0; |
| 103 | else l=to_int(exp(log(to_float(val))*0.32)); |
| 104 | |
| 105 | ret += l; |
| 106 | |
| 107 | DEBUG("Nach XP: ret = %d\n", ret); |
| 108 | |
| 109 | // Beitrag E: Zaubertraenke |
| 110 | // Gefundene Traenke geben 5 LEP |
| 111 | // Die Heiltraenke geben zusaetzlich 10+20+30+40 LEP |
| 112 | i = 80 - (val = sizeof((int *)pl->QueryProp(P_POTIONROOMS))); |
| 113 | |
| 114 | ret += 5*i + ([ 0: 100, 1: 60, 2: 30, 3: 10])[val]; |
| 115 | |
| 116 | // Beitrag F: Forscherpunkte |
| 117 | // Pro FP gibt es 6 Stufenpunkte |
| 118 | ret += 6 * (int)EPMASTER->QueryExplorationPoints(pl); |
| 119 | |
| 120 | DEBUG("Nach FP: ret = %d\n", ret); |
| 121 | |
| 122 | // Beitrag G: Gildeneinstufung |
| 123 | // Maximale Gildeneinstufung (10000) entspricht vier Leveln |
| 124 | ret += ((int)pl->QueryProp(P_GUILD_RATING))/25; |
| 125 | |
| 126 | DEBUG("Nach GR: ret = %d\n", ret); |
| 127 | |
| 128 | // Ausgabe gibt es nur in 20er-Schritten |
| 129 | ret -= ret%20; |
| 130 | |
| 131 | return (ret > 100) ? ret : 100; |
| 132 | |
| 133 | } |
| 134 | |
| 135 | nomask int QueryLEP() |
| 136 | { |
| 137 | if (!previous_object()) |
| 138 | return 0; |
| 139 | return QueryLEPForPlayer(previous_object()); |
| 140 | } |
| 141 | |
| 142 | nomask int QueryLevel(int lep) { |
| 143 | if (lep<=0) |
| 144 | lep=QueryLEP(); |
| 145 | |
| 146 | if (lep<=0) |
| 147 | return 0; |
| 148 | |
| 149 | #ifdef __PFOERKL__ |
| 150 | // normale Level alle 100 LEP |
| 151 | if (lep >= 500) |
| 152 | return lep/100 + 4; |
| 153 | else { |
| 154 | // level mit weniger LEP am Anfang (1-8) |
| 155 | // Level aus der LOW_LEVEL_LEP_LIST raussuchen. |
| 156 | int lev = sizeof(LOW_LEVEL_LEP_LIST) - 1; |
| 157 | for ( ; lev >= 0; --lev) { |
| 158 | if (LOW_LEVEL_LEP_LIST[lev] <= lep) |
| 159 | break; // gefunden |
| 160 | } |
| 161 | return lev+1; |
| 162 | } |
| 163 | #else |
| 164 | return lep/100; |
| 165 | #endif // __PFOERKL__ |
| 166 | return 0; |
| 167 | } |
| 168 | |
| 169 | // Wieviele LEP fehlen zum naechsten Level? |
| 170 | nomask int QueryNextLevelLEP(int lvl, int lep) { |
| 171 | int needed; |
| 172 | |
| 173 | if (QueryLevel(lep) > lvl) |
| 174 | return 0; |
| 175 | |
| 176 | #ifdef __PFOERKL__ |
| 177 | if (lvl < sizeof(LOW_LEVEL_LEP_LIST)) |
| 178 | needed = LOW_LEVEL_LEP_LIST[lvl]; |
| 179 | else |
| 180 | needed = (lvl-3) * 100; // (lvl + 1 - 4) * 100 |
| 181 | #else |
| 182 | needed = (lvl+1) * 100; |
| 183 | #endif // __PFOERKL__ |
| 184 | |
| 185 | // needed sind jetzt die insgesamt benoetigten LEP. Vorhandene abziehen. |
| 186 | needed -= lep; |
| 187 | // nix < 0 zurueckliefern |
| 188 | return max(needed,0); |
| 189 | } |
| 190 | |
| 191 | string QueryForschung() |
| 192 | { |
| 193 | int max, my, avg; |
| 194 | string ret; |
| 195 | |
| 196 | if ((my=(int)EPMASTER->QueryExplorationPoints(getuid(previous_object()))) < MIN_EP) |
| 197 | return "Du kennst Dich im "MUDNAME" so gut wie gar nicht aus.\n"; |
| 198 | |
| 199 | my *= 100; |
| 200 | max = my/(int)EPMASTER->QueryMaxEP(); |
| 201 | avg = my/(int)EPMASTER->QueryAverage(); |
| 202 | |
| 203 | ret = "Verglichen mit Deinen Mitspielern, kennst Du Dich im "MUDNAME" "; |
| 204 | switch(avg) { |
| 205 | case 0..10: |
| 206 | ret += "kaum"; |
| 207 | break; |
| 208 | case 11..40: |
| 209 | ret += "aeusserst schlecht"; |
| 210 | break; |
| 211 | case 41..56: |
| 212 | ret += "sehr schlecht"; |
| 213 | break; |
| 214 | case 57..72: |
| 215 | ret += "schlecht"; |
| 216 | break; |
| 217 | case 73..93: |
| 218 | ret += "unterdurchschnittlich"; |
| 219 | break; |
| 220 | case 94..109: |
| 221 | ret += "durchschnittlich gut"; |
| 222 | break; |
| 223 | case 110..125: |
| 224 | ret += "besser als der Durchschnitt"; |
| 225 | break; |
| 226 | case 126..145: |
| 227 | ret += "recht gut"; |
| 228 | break; |
| 229 | case 146..170: |
| 230 | ret += "ziemlich gut"; |
| 231 | break; |
| 232 | case 171..210: |
| 233 | ret += "gut"; |
| 234 | break; |
| 235 | case 211..300: |
| 236 | ret += "sehr gut"; |
| 237 | break; |
| 238 | case 301..400: |
| 239 | ret += "ausserordentlich gut"; |
| 240 | break; |
| 241 | case 401..500: |
| 242 | ret += "unheimlich gut"; |
| 243 | break; |
| 244 | default: |
| 245 | ret += "einfach hervorragend"; |
| 246 | break; |
| 247 | } |
| 248 | ret += " aus.\nAbsolut gesehen "; |
| 249 | |
| 250 | switch(max) { |
| 251 | case 0..5: |
| 252 | ret += "kennst Du nur wenig vom "MUDNAME"."; |
| 253 | break; |
| 254 | case 6..10: |
| 255 | ret += "solltest Du Dich vielleicht noch genauer umsehen."; |
| 256 | break; |
| 257 | case 11..17: |
| 258 | ret += "bist Du durchaus schon herumgekommen."; |
| 259 | break; |
| 260 | case 18..25: |
| 261 | ret += "hast Du schon einiges gesehen."; |
| 262 | break; |
| 263 | case 26..35: |
| 264 | ret += "bist Du schon weit herumgekommen."; |
| 265 | break; |
| 266 | case 36..50: |
| 267 | ret += "koenntest Du eigentlich einen Reisefuehrer herausbringen."; |
| 268 | break; |
| 269 | case 51..75: |
| 270 | ret += "hast Du schon sehr viel gesehen."; |
| 271 | break; |
| 272 | default: |
| 273 | ret += "besitzt Du eine hervorragende Ortskenntnis."; |
| 274 | } |
| 275 | return break_string(ret, 78, 0, 1); |
| 276 | } |
| 277 | |
| 278 | |
| 279 | nomask mixed QueryWizardRequirements(object player) |
| 280 | { |
| 281 | // Diese Funktion gibt ein 2-elementiges Array zurueck, in dem im ersten |
| 282 | // Element steht, ob der Spieler Seher werden kann (1) oder |
| 283 | // nicht (0) und im zweiten Element steht, was genau ihm noch |
| 284 | // fehlt. |
| 285 | // Fehlercode ist ({-1, ""}) |
| 286 | |
| 287 | // Die Umrechnungsfaktoren wurden einfach aus QueryLEP uebernommen; ggf. |
| 288 | // kann man das einmal in Unterfunktionen auslagern. |
| 289 | |
| 290 | mixed ret; |
| 291 | string s; |
| 292 | int i,z,val; |
| 293 | |
| 294 | ret = ({-1, "Hier ist etwas schief gelaufen. Bitte einen Erzmagier\n" |
| 295 | +"benachrichtigen.\n"}); |
| 296 | s = ""; |
| 297 | i = 0; |
| 298 | |
| 299 | if(!player || !objectp(player)) |
| 300 | player=(this_player()?this_player():this_interactive()); |
| 301 | |
| 302 | if(!player) |
| 303 | return ({-1,""}); |
| 304 | |
| 305 | DEBUG("Es geht um: %O\n", player); |
| 306 | |
| 307 | // Abenteuerpunkte |
| 308 | DEBUG("Abenteuerpunkte: %d ("+REQ_QP+")\n", player->QueryProp(P_QP)); |
| 309 | if (player->QueryProp(P_QP) < REQ_QP) { |
| 310 | s += sprintf(" * Dir fehlen noch mindestens %d Abenteuerpunkte.\n", |
| 311 | REQ_QP - (int)player->QueryProp(P_QP)); |
| 312 | i--; |
| 313 | } |
| 314 | |
| 315 | // Forscherpunkte |
| 316 | z = 6 * (int)EPMASTER->QueryExplorationPoints(player); |
| 317 | DEBUG("Forscherpunkte: %d ("+REQ_EP+")\n", z); |
| 318 | if (z < REQ_EP) { |
| 319 | s += sprintf(" * Du kennst Dich im "MUDNAME" noch nicht genug aus, " |
| 320 | +"genau genommen\n musst Du Dir noch %s ansehen.\n", |
| 321 | REQ_TEXT1[(z*10/REQ_EP)] ); |
| 322 | i--; |
| 323 | } |
| 324 | |
| 325 | // Zaubertraenke |
| 326 | z = 80 - (val = sizeof((int*)player->QueryProp(P_POTIONROOMS))); |
| 327 | z = z*5 + ([0:100, 1:60, 2:30, 3:10])[val]; |
| 328 | DEBUG("Zaubertraenke: %d ("+REQ_P+")\n", z); |
| 329 | if (z < REQ_P) { |
| 330 | s += sprintf(" * Du musst noch einige Zaubertraenke (ca. %d) suchen.\n", |
| 331 | (REQ_P - z)/5 ); |
| 332 | i--; |
| 333 | } |
| 334 | |
| 335 | // Erstkills |
| 336 | z = (int)SCOREMASTER->QueryKillPoints(player); |
| 337 | DEBUG("Erstkills: %d ("+REQ_K+")\n", z); |
| 338 | if (z < REQ_K) { |
| 339 | s += sprintf(" * Du hast noch nicht genuegend wuerdige Gegner erlegt, genau " |
| 340 | +"genommen\n musst Du noch %s wuerdige Monster toeten.\n", |
| 341 | REQ_TEXT2[(z*10/REQ_K)] );; |
| 342 | i--; |
| 343 | } |
| 344 | |
| 345 | int minlevel = QueryLevel(REQ_LEP); |
| 346 | |
| 347 | // Restliche Stufenpunkte |
| 348 | DEBUG("Stufenpunkte: %d ("+REQ_LEP+")\n", player->QueryProp(P_LEP)); |
| 349 | if ((int)(player->QueryProp(P_LEP)) < REQ_LEP) { |
| 350 | s += sprintf(" * Du musst mindestens %d Stufenpunkte, entspricht Stufe %d, " |
| 351 | "erreichen.\n", REQ_LEP, minlevel); |
| 352 | i--; |
| 353 | } |
| 354 | |
| 355 | // Demnach mindestens REQ/100-Level |
| 356 | DEBUG("Level: %d ("+REQ_LEP/100+")\n", player->QueryProp(P_LEVEL)); |
| 357 | if ((int)player->QueryProp(P_LEVEL) < minlevel) { |
| 358 | s += sprintf(" * Du musst mindestens Stufe %d erreichen.\n", minlevel); |
| 359 | i--; |
| 360 | } |
| 361 | |
| 362 | if(i<0) { |
| 363 | ret = ({-1, |
| 364 | sprintf("Du hast noch nicht alle Seher-Anforderungen erfuellt.\n" |
| 365 | +"Im einzelnen fehlt Dir folgendes:\n\n%s\n" |
| 366 | +break_string("Falls Du Dir nun dennoch unsicher bist, " |
| 367 | +"welche Anforderungen Du erfuellen musst, dann " |
| 368 | +"schaue bei 'hilfe seher' und 'hilfe stufenpunkte' doch einfach noch " |
| 369 | +"einmal nach. Sind dann " |
| 370 | +"immer noch Dinge offen oder unklar, so sprich einfach einen " |
| 371 | +"der Erzmagier an.", 78,0,1),s) }); |
| 372 | } |
| 373 | |
| 374 | if (i==0) { |
| 375 | ret = ({1, break_string( |
| 376 | "Du hast alle Seher-Anforderungen erfuellt. Wende Dich doch " |
| 377 | +"einmal an Merlin und frage ihn, ob er Dich befoerdert.", |
| 378 | 78,0,1) }); |
| 379 | } |
| 380 | |
| 381 | return ret; |
| 382 | } |
| 383 | |
| 384 | nomask int QueryReadyForWiz(object player) |
| 385 | { |
| 386 | mixed r; |
| 387 | |
| 388 | r = QueryWizardRequirements(player); |
| 389 | |
| 390 | if (!pointerp(r) && sizeof(r)!=2 && !intp(r[0])) |
| 391 | return -1; |
| 392 | |
| 393 | return r[0]; |
| 394 | } |
| 395 | |
| 396 | nomask string QueryReadyForWizText(object player) |
| 397 | { |
| 398 | mixed r; |
| 399 | |
| 400 | r = QueryWizardRequirements(player); |
| 401 | |
| 402 | if (!pointerp(r) && sizeof(r)!=2 && !stringp(r[1])) |
| 403 | return "Hier ist etwas schief gegangen, bitte verstaendige einen " |
| 404 | +"Erzmagier."; |
| 405 | |
| 406 | return r[1]; |
| 407 | } |
| 408 | |