OpenMW
components/interpreter/miscopcodes.hpp
Go to the documentation of this file.
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