OpenMW
|
00001 #ifndef INTERPRETER_MISCOPCODES_H_INCLUDED 00002 #define INTERPRETER_MISCOPCODES_H_INCLUDED 00003 00004 #include <cstdlib> 00005 #include <stdexcept> 00006 #include <vector> 00007 #include <string> 00008 #include <sstream> 00009 #include <algorithm> 00010 00011 #include "opcodes.hpp" 00012 #include "runtime.hpp" 00013 #include "defines.hpp" 00014 00015 namespace Interpreter 00016 { 00017 inline std::string formatMessage (const std::string& message, Runtime& runtime) 00018 { 00019 std::string formattedMessage; 00020 00021 for (std::size_t i=0; i<message.size(); ++i) 00022 { 00023 char c = message[i]; 00024 00025 if (c!='%') 00026 formattedMessage += c; 00027 else 00028 { 00029 ++i; 00030 if (i<message.size()) 00031 { 00032 c = message[i]; 00033 00034 if (c=='S' || c=='s') 00035 { 00036 int index = runtime[0].mInteger; 00037 runtime.pop(); 00038 formattedMessage += runtime.getStringLiteral (index); 00039 } 00040 else if (c=='g' || c=='G') 00041 { 00042 Type_Integer value = runtime[0].mInteger; 00043 runtime.pop(); 00044 00045 std::ostringstream out; 00046 out << value; 00047 formattedMessage += out.str(); 00048 } 00049 else if (c=='f' || c=='F' || c=='.') 00050 { 00051 while (c!='f' && i<message.size()) 00052 { 00053 ++i; 00054 } 00055 00056 float value = runtime[0].mFloat; 00057 runtime.pop(); 00058 00059 std::ostringstream out; 00060 out << value; 00061 formattedMessage += out.str(); 00062 } 00063 else if (c=='%') 00064 formattedMessage += "%"; 00065 else 00066 { 00067 formattedMessage += "%"; 00068 formattedMessage += c; 00069 } 00070 } 00071 } 00072 } 00073 00074 formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext()); 00075 return formattedMessage; 00076 } 00077 00078 class OpMessageBox : public Opcode1 00079 { 00080 public: 00081 00082 virtual void execute (Runtime& runtime, unsigned int arg0) 00083 { 00084 // message 00085 int index = runtime[0].mInteger; 00086 runtime.pop(); 00087 std::string message = runtime.getStringLiteral (index); 00088 00089 // buttons 00090 std::vector<std::string> buttons; 00091 00092 for (std::size_t i=0; i<arg0; ++i) 00093 { 00094 int index = runtime[0].mInteger; 00095 runtime.pop(); 00096 buttons.push_back (runtime.getStringLiteral (index)); 00097 } 00098 00099 std::reverse (buttons.begin(), buttons.end()); 00100 00101 // handle additional parameters 00102 std::string formattedMessage = formatMessage (message, runtime); 00103 00104 runtime.getContext().messageBox (formattedMessage, buttons); 00105 } 00106 }; 00107 00108 class OpReport : public Opcode0 00109 { 00110 public: 00111 00112 virtual void execute (Runtime& runtime) 00113 { 00114 // message 00115 int index = runtime[0].mInteger; 00116 runtime.pop(); 00117 std::string message = runtime.getStringLiteral (index); 00118 00119 // handle additional parameters 00120 std::string formattedMessage = formatMessage (message, runtime); 00121 00122 runtime.getContext().report (formattedMessage); 00123 } 00124 }; 00125 00126 class OpMenuMode : public Opcode0 00127 { 00128 public: 00129 00130 virtual void execute (Runtime& runtime) 00131 { 00132 runtime.push (runtime.getContext().menuMode()); 00133 } 00134 }; 00135 00136 class OpRandom : public Opcode0 00137 { 00138 public: 00139 00140 virtual void execute (Runtime& runtime) 00141 { 00142 double r = static_cast<double> (std::rand()) / RAND_MAX; // [0, 1) 00143 00144 Type_Integer limit = runtime[0].mInteger; 00145 00146 if (limit<0) 00147 throw std::runtime_error ( 00148 "random: argument out of range (Don't be so negative!)"); 00149 00150 Type_Integer value = static_cast<Type_Integer> (r*limit); // [o, limit) 00151 00152 runtime[0].mInteger = value; 00153 } 00154 }; 00155 00156 class OpGetSecondsPassed : public Opcode0 00157 { 00158 public: 00159 00160 virtual void execute (Runtime& runtime) 00161 { 00162 Type_Float duration = runtime.getContext().getSecondsPassed(); 00163 00164 runtime.push (duration); 00165 } 00166 }; 00167 00168 class OpEnable : public Opcode0 00169 { 00170 public: 00171 00172 virtual void execute (Runtime& runtime) 00173 { 00174 runtime.getContext().enable(); 00175 } 00176 }; 00177 00178 class OpDisable : public Opcode0 00179 { 00180 public: 00181 00182 virtual void execute (Runtime& runtime) 00183 { 00184 runtime.getContext().disable(); 00185 } 00186 }; 00187 00188 class OpGetDisabled : public Opcode0 00189 { 00190 public: 00191 00192 virtual void execute (Runtime& runtime) 00193 { 00194 runtime.push (runtime.getContext().isDisabled()); 00195 } 00196 }; 00197 00198 class OpEnableExplicit : public Opcode0 00199 { 00200 public: 00201 00202 virtual void execute (Runtime& runtime) 00203 { 00204 int index = runtime[0].mInteger; 00205 runtime.pop(); 00206 std::string id = runtime.getStringLiteral (index); 00207 00208 runtime.getContext().enable (id); 00209 } 00210 }; 00211 00212 class OpDisableExplicit : public Opcode0 00213 { 00214 public: 00215 00216 virtual void execute (Runtime& runtime) 00217 { 00218 int index = runtime[0].mInteger; 00219 runtime.pop(); 00220 std::string id = runtime.getStringLiteral (index); 00221 00222 runtime.getContext().disable (id); 00223 } 00224 }; 00225 00226 class OpGetDisabledExplicit : public Opcode0 00227 { 00228 public: 00229 00230 virtual void execute (Runtime& runtime) 00231 { 00232 int index = runtime[0].mInteger; 00233 runtime.pop(); 00234 std::string id = runtime.getStringLiteral (index); 00235 00236 runtime.push (runtime.getContext().isDisabled (id)); 00237 } 00238 }; 00239 00240 } 00241 00242 #endif