MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // MorgenGrauen MUDlib |
| 2 | // |
| 3 | // restriction_checker.c -- Beschraenkungen in Gilden, Spells und Skills |
| 4 | // |
| 5 | // $Id: restriction_checker.c 8754 2014-04-26 13:12:58Z Zesstra $ |
| 6 | #pragma strong_types |
| 7 | #pragma save_types |
| 8 | #pragma no_clone |
| 9 | #pragma pedantic |
| 10 | //#pragma range_check |
| 11 | #pragma no_shadow |
| 12 | |
| 13 | inherit "/std/util/executer"; |
| 14 | |
| 15 | #define NEED_PROTOTYPES |
| 16 | #include <thing/properties.h> |
| 17 | #include <properties.h> |
| 18 | #include <new_skills.h> |
| 19 | #include <wizlevels.h> |
| 20 | #include <questmaster.h> |
| 21 | |
| 22 | #define DEBUG(x) if (find_player("zesstra")) tell_object(find_player("zesstra"),x) |
| 23 | |
| 24 | // erweitert um das <pl> argument und die extra-Argument, die bereits in <fun> |
| 25 | // angegeben wurden. (*grummel*) |
| 26 | protected mixed execute_anything(mixed fun, object pl, varargs mixed args) |
| 27 | { |
| 28 | //DEBUG(sprintf("ex_any(): Fun: %O, Ob: %O, args: %O\n",fun,pl,args)); |
| 29 | // wenn in fun schon extraargumente stehen, dann pl einfuegen und args |
| 30 | // dranhaengen. |
| 31 | if (pointerp(fun) && sizeof(fun) > 2) |
| 32 | { |
| 33 | // args kann ({}) sein, wenn keine Extraargumente uebergeben wurden, macht |
| 34 | // aber nix. |
| 35 | args = ({pl}) + fun[2..] + args; |
| 36 | fun = fun[0..1]; |
| 37 | return ::execute_anything(fun, args...); |
| 38 | } |
| 39 | // s.o. |
| 40 | return ::execute_anything(fun, pl, args...); |
| 41 | } |
| 42 | |
| 43 | mapping race_modifier(object pl, mapping map_ldfied) { |
| 44 | mapping rmap,help; |
| 45 | |
| 46 | if (mappingp(map_ldfied) && member(map_ldfied,SM_RACE) && objectp(pl) && |
| 47 | mappingp(rmap=map_ldfied[SM_RACE])) |
| 48 | // if (mappingp(help=rmap[pl->_query_real_race()])) |
| 49 | if (mappingp(help=rmap[pl->QueryProp(P_REAL_RACE)])) |
| 50 | return map_ldfied+help; |
| 51 | else if(member(rmap,"*") && mappingp(help=rmap["*"])) |
| 52 | return map_ldfied+help; |
| 53 | return map_ldfied; |
| 54 | } |
| 55 | |
| 56 | string |
| 57 | check_restrictions(object pl, mapping restr) { |
| 58 | /* Folgende Einschraenkungen koennen geprueft werden: |
| 59 | * - Mindestwerte bei allen Attributen und Properties Level, QP, XP |
| 60 | * - bestimmte Rassen koennen ausgeschlossen werden bzw. erlaubt werden |
| 61 | * (SR_EXCLUDE_RACE ist ein Array von ausgeschlossenen Rassen, |
| 62 | * SR_INCLUDE_RACE eines mit eingeschlossenen) |
| 63 | * - SR_RACE kann ein Mapping sein, dass Rassen ein eigenes |
| 64 | * Restriction-mapping zuordnet. "*" steht fuer alle anderen Rassen. |
| 65 | */ |
| 66 | closure cl,cl2; |
| 67 | string race, guild; |
| 68 | |
| 69 | if (!mappingp(restr) || !sizeof(restr)) return 0; // Keine Einschraenkungen |
| 70 | if (!objectp(pl)) return ""; |
| 71 | if (pl->QueryDisguise()) |
| 72 | return "Zieh erst mal den Tarnhelm aus.\n"; |
| 73 | |
| 74 | restr=race_modifier(&pl,&restr); |
| 75 | |
| 76 | cl=symbol_function("QueryProp",pl); |
| 77 | cl2=symbol_function("QueryAttribute",pl); |
| 78 | |
| 79 | foreach(string to_check, mixed condition: restr) |
| 80 | { |
| 81 | switch(to_check) |
| 82 | { |
| 83 | case P_LEVEL: |
| 84 | if (funcall(cl,P_LEVEL) < condition) |
| 85 | return "Deine Stufe reicht dafuer nicht aus.\n"; |
| 86 | break; |
| 87 | case P_GUILD_LEVEL: |
| 88 | if (funcall(cl,P_GUILD_LEVEL) < condition) |
| 89 | return "Deine Gildenstufe reicht dafuer nicht aus.\n"; |
| 90 | break; |
| 91 | case SR_SEER: // das macht nun wahrlich nur bei interactives sinn!!! |
| 92 | if (condition && query_once_interactive(pl) && !IS_SEER(pl)) |
| 93 | return "Du musst dazu erst Seher werden.\n"; |
| 94 | break; |
| 95 | case P_XP: |
| 96 | if (funcall(cl,P_XP) < condition) |
| 97 | return "Du hast nicht genuegend Erfahrung dafuer.\n"; |
| 98 | break; |
| 99 | case P_QP: |
| 100 | if (funcall(cl,P_QP) < condition) |
| 101 | return "Du hast nicht genuegend Aufgaben geloest.\n"; |
| 102 | break; |
| 103 | case P_ALCOHOL: |
| 104 | if (funcall(cl,P_ALCOHOL) >= condition) |
| 105 | return "Du bist zu besoffen.\n"; |
| 106 | break; |
| 107 | case P_DRINK: |
| 108 | if (funcall(cl,P_DRINK) >= condition) |
| 109 | return "Du hast zuviel getrunken.\n"; |
| 110 | break; |
| 111 | case P_FOOD: |
| 112 | if (funcall(cl,P_FOOD) >= condition) |
| 113 | return "Du hast zuviel gegessen.\n"; |
| 114 | break; |
| 115 | case P_DEAF: |
| 116 | if (funcall(cl,P_DEAF)) |
| 117 | return "Du kannst nichts hoeren.\n"; |
| 118 | break; |
| 119 | case P_BLIND: |
| 120 | if (funcall(cl,P_BLIND)) |
| 121 | return "Du kannst nichts sehen.\n"; |
| 122 | break; |
| 123 | case P_FROG: |
| 124 | if (funcall(cl,P_FROG)) |
| 125 | return "Als Frosch kannst Du das leider nicht.\n"; |
| 126 | break; |
| 127 | case A_INT: |
| 128 | if (funcall(cl2,A_INT) < condition) |
| 129 | return "Deine Intelligenz reicht dafuer nicht aus.\n"; |
| 130 | break; |
| 131 | case A_DEX: |
| 132 | if (funcall(cl2,A_DEX) < condition) |
| 133 | return "Deine Geschicklichkeit reicht dafuer nicht aus.\n"; |
| 134 | break; |
| 135 | case A_CON: |
| 136 | if (funcall(cl2,A_CON) < condition) |
| 137 | return "Deine Ausdauer reicht dafuer nicht aus.\n"; |
| 138 | break; |
| 139 | case A_STR: |
| 140 | if (funcall(cl2,A_STR) < condition) |
| 141 | return "Deine Staerke reicht dafuer nicht aus.\n"; |
| 142 | break; |
| 143 | case SR_BAD: |
| 144 | if (funcall(cl,P_ALIGN) < condition) |
| 145 | return "Du bist zu boese.\n"; |
| 146 | break; |
| 147 | case SR_GOOD: |
| 148 | if (funcall(cl,P_ALIGN) > condition) |
| 149 | return "Du bist nicht boese genug.\n"; |
| 150 | break; |
| 151 | case SR_MIN_SIZE: |
| 152 | if (funcall(cl,P_SIZE) < condition) |
| 153 | return "Du bist dafuer zu klein.\n"; |
| 154 | break; |
| 155 | case SR_MAX_SIZE: |
| 156 | if (funcall(cl,P_SIZE) > condition) |
| 157 | return "Du bist dafuer zu gross.\n"; |
| 158 | break; |
| 159 | case SR_FREE_HANDS: |
| 160 | if (condition > (funcall(cl,P_MAX_HANDS)-funcall(cl,P_USED_HANDS))) |
| 161 | return "Du hast nicht genug freie Haende dafuer.\n"; |
| 162 | break; |
| 163 | case SR_EXCLUDE_RACE: |
| 164 | if (IS_LEARNER(pl)) |
| 165 | race=funcall(cl,P_RACE); |
| 166 | else |
| 167 | race=funcall(cl,P_REAL_RACE); //race=pl->_query_real_race(); |
| 168 | if ( pointerp(condition) && member(condition,race)>=0 ) |
| 169 | return ("Als "+race+" kannst Du das nicht.\n"); |
| 170 | break; |
| 171 | case SR_INCLUDE_RACE: |
| 172 | if (IS_LEARNER(pl)) |
| 173 | race=funcall(cl,P_RACE); |
| 174 | else |
| 175 | race=funcall(cl,P_REAL_RACE); //race=pl->_query_real_race(); |
| 176 | if (pointerp(condition) && member(condition,race)<0) |
| 177 | return ("Als "+race+" kannst Du das nicht.\n"); |
| 178 | break; |
| 179 | case SR_EXCLUDE_GUILD: |
| 180 | guild=funcall(cl,P_GUILD); |
| 181 | if (pointerp(condition) && member(condition,guild)>=0) |
| 182 | return ("Mit Deiner Gildenzugehoerigkeit kannst Du das nicht.\n"); |
| 183 | break; |
| 184 | case SR_INCLUDE_GUILD: |
| 185 | guild=funcall(cl,P_GUILD); |
| 186 | if (pointerp(condition) && member(condition,guild)<0) |
| 187 | return ("Mit Deiner Gildenzugehoerigkeit kannst Du das nicht.\n"); |
| 188 | break; |
| 189 | case SR_FUN: |
| 190 | string res=execute_anything(condition, pl); |
| 191 | if (stringp(res)) |
| 192 | return res; |
| 193 | break; |
| 194 | case SR_PROP: |
| 195 | foreach ( string propname, mixed value, string msg: condition ) { |
| 196 | if ( funcall(cl, propname) != value ) |
| 197 | return ( stringp(msg) && sizeof(msg) ? msg : |
| 198 | "Koennte es sein, dass Du vergessen hast, etwas zu " |
| 199 | "erledigen?\n"); |
| 200 | } |
| 201 | break; |
| 202 | case SR_QUEST: |
| 203 | if (pointerp(condition)) |
| 204 | { |
| 205 | // geloeste Quests aus der Liste der Bedingungen entfernen |
| 206 | condition -= filter(condition, "QueryQuest", pl); |
| 207 | if ( sizeof(condition) ) |
| 208 | return ("Du musst zuerst das Abenteuer '"+condition[0]+ |
| 209 | "' loesen.\n"); |
| 210 | } |
| 211 | break; |
| 212 | case SR_MINIQUEST: |
| 213 | if (pointerp(condition)) |
| 214 | { |
| 215 | closure unsolved_MQs = function int (mixed mq_num) |
| 216 | { return !(QM)->HasMiniQuest(pl, mq_num); }; |
| 217 | if ( sizeof(filter(condition, unsolved_MQs)) ) |
| 218 | return "Du hast eine benoetigte Miniquest noch nicht geloest.\n"; |
| 219 | // Der Name der MQ wird absichtlich nicht explizit ausgegeben. |
| 220 | } |
| 221 | break; |
| 222 | } // switch |
| 223 | } // foreach |
| 224 | return 0; |
| 225 | } |
| 226 | |
| 227 | varargs mixed |
| 228 | GetData(string dname, mapping map_ldfied, object pl) { |
| 229 | mixed dat,res; |
| 230 | |
| 231 | if (!dname || !mappingp(map_ldfied)) return 0; |
| 232 | if (closurep(dat=map_ldfied[dname]) && (res=funcall(dat,pl,map_ldfied))) |
| 233 | return res; |
| 234 | return dat; |
| 235 | |
| 236 | } |
| 237 | |
| 238 | varargs int |
| 239 | GetValue(string vname, mapping map_ldfied, object pl) { |
| 240 | mixed dat,res; |
| 241 | |
| 242 | // printf("GetValue(%O): %O\n",vname,map_ldfied); |
| 243 | if (!vname || !map_ldfied) return 0; |
| 244 | if ((dat=map_ldfied[vname]) && (res=execute_anything(dat,pl,map_ldfied))) |
| 245 | return res; |
| 246 | // printf("Value: %O\n",dat); |
| 247 | return intp(dat) ? dat : 0; |
| 248 | } |
| 249 | |
| 250 | varargs int |
| 251 | GetFactor(string fname, mapping map_ldfied, object pl) { |
| 252 | mixed res; |
| 253 | |
| 254 | // printf("GetFactor(%O):\n",fname); |
| 255 | if (!fname || !(res=GetValue(FACTOR(fname),map_ldfied,pl))) |
| 256 | return 100; |
| 257 | if (res<10) res=10; |
| 258 | else if (res>1000) res=1000; |
| 259 | // printf("Factor: %O\n",res); |
| 260 | return res; |
| 261 | } |
| 262 | |
| 263 | varargs int |
| 264 | GetOffset(string oname, mapping map_ldfied, object pl) { |
| 265 | mixed res; |
| 266 | |
| 267 | // printf("GetOffset(%O):\n",oname); |
| 268 | if (!oname || !(res=GetValue(OFFSET(oname),map_ldfied,pl))) |
| 269 | return 0; |
| 270 | if (res<-10000) res=-10000; |
| 271 | else if (res>10000) res=10000; |
| 272 | // printf("Offset: %O\n",res); |
| 273 | return res; |
| 274 | } |
| 275 | |
| 276 | varargs int |
| 277 | GetFValue(string vname, mapping map_ldfied, object pl) { |
| 278 | return (GetValue(vname,map_ldfied,pl)*GetFactor(vname,map_ldfied,pl))/100; |
| 279 | } |
| 280 | |
| 281 | varargs int |
| 282 | GetValueO(string vname, mapping map_ldfied, object pl) { |
| 283 | return GetValue(vname,map_ldfied,pl)+GetOffset(vname,map_ldfied,pl); |
| 284 | } |
| 285 | |
| 286 | varargs int |
| 287 | GetFValueO(string vname, mapping map_ldfied, object pl) { |
| 288 | return ((GetValue(vname,map_ldfied,pl)*GetFactor(vname,map_ldfied,pl))/100 |
| 289 | + GetOffset(vname,map_ldfied,pl)); |
| 290 | } |
| 291 | |
| 292 | varargs int |
| 293 | GetRandFValueO(string vname, mapping map_ldfied, object pl) { |
| 294 | return (random(GetValue(vname,map_ldfied,pl)*GetFactor(vname,map_ldfied,pl))/100 |
| 295 | + GetOffset(vname,map_ldfied,pl)); |
| 296 | } |
| 297 | |
| 298 | mapping AddSkillMappings(mapping oldmap, mapping newmap) { |
| 299 | mapping res,t1,t2; |
| 300 | mixed *inx,ind; |
| 301 | int i; |
| 302 | |
| 303 | if (!mappingp(oldmap)) return newmap; |
| 304 | if (!mappingp(newmap)) return oldmap; |
| 305 | inx=({SI_SKILLRESTR_LEARN,SI_SKILLRESTR_USE,SM_RACE}); |
| 306 | res=oldmap+newmap; |
| 307 | for (i=sizeof(inx);i--;) { |
| 308 | ind=inx[i]; |
| 309 | t1=oldmap[ind]; |
| 310 | t2=newmap[ind]; |
| 311 | if (t1) { |
| 312 | if (t2) |
| 313 | res[ind]=t1+t2; |
| 314 | else |
| 315 | res[ind]=t1; |
| 316 | } else { |
| 317 | if (t2) |
| 318 | res[ind]=t2; |
| 319 | } |
| 320 | } |
| 321 | return res; |
| 322 | } |
| 323 | |