diff --git a/configure b/configure index 1c54a7b44d..a4a379f5ea 100755 --- a/configure +++ b/configure @@ -54,8 +54,9 @@ if [ "$1" = "--reconfig" ] || [ "$1" = "--reconfigure" ]; then # Make sure we don't lock config.cache cat config.cache | sed 's@\\ @\\\\ @g' > cache.tmp sh cache.tmp + RET=$? rm -f cache.tmp - exit $? + exit $RET fi set_default diff --git a/docs/obg_format.txt b/docs/obg_format.txt index 272ac5dcf8..87fe11a71b 100644 --- a/docs/obg_format.txt +++ b/docs/obg_format.txt @@ -49,6 +49,8 @@ tropical = TRGH.GRF ; GRF file with extra toyland sprites toyland = TRGT.GRF ; NewGRF file using Actions 5, 7, 9 and A to replace sprites +; Must use a GRF ID starting with FF so it cannot be selected from +; the in-game NewGRF list and (thus) be loaded twice. extra = OPENTTDD.GRF ; The md5s section lists the MD5 checksum for the files that replace them. diff --git a/os/win32/installer/install.nsi b/os/win32/installer/install.nsi index d0b2c9833b..40ff8b0070 100644 --- a/os/win32/installer/install.nsi +++ b/os/win32/installer/install.nsi @@ -71,10 +71,6 @@ Page custom SelectCDEnter SelectCDExit ": TTD folder" !insertmacro MUI_PAGE_INSTFILES -;----------------------------------------------------- -; New custom page to show UNICODE and MSLU information -Page custom ShowWarningsPage - !define MUI_FINISHPAGE_TITLE_3LINES !define MUI_FINISHPAGE_RUN_TEXT "Run ${APPNAMEANDVERSION} now!" !define MUI_FINISHPAGE_RUN "$INSTDIR\openttd.exe" @@ -133,7 +129,6 @@ Section "!OpenTTD" Section1 ; Delete old files from the main dir. they are now placed in data/ and lang/ Delete "$INSTDIR\*.lng" Delete "$INSTDIR\*.grf" - Delete "$INSTDIR\*.obg" Delete "$INSTDIR\sample.cat" Delete "$INSTDIR\ttd.exe" @@ -372,23 +367,6 @@ WinNT: ClearErrors FunctionEnd -;---------------------------------------------------------------------------------- -; Custom page function to show notices for running OpenTTD (only for win32 systems) -; We have extracted this custom page as Notice in the .onInit function -Function ShowWarningsPage - Call GetWindowsVersion - Pop $R0 - ; Don't show the UNICODE notice if the installer is run on Win9x systems - StrCmp $R0 "win9x" 0 WinNT - Abort -WinNT: - !insertmacro MUI_HEADER_TEXT "Installation Complete" "Important notices for OpenTTD usage." - !insertmacro MUI_INSTALLOPTIONS_EXTRACT_AS "notice.ini" "Notice" - !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "Notice" - ClearErrors - !insertmacro MUI_INSTALLOPTIONS_SHOW -FunctionEnd - ;------------------------------------------------------------------------------- ; Determine windows version, returns "win9x" if Win9x/Me or "winnt" on the stack Function GetWindowsVersion diff --git a/os/win32/installer/notice.ini b/os/win32/installer/notice.ini deleted file mode 100644 index 7e51c0dba2..0000000000 --- a/os/win32/installer/notice.ini +++ /dev/null @@ -1,30 +0,0 @@ -; Ini file generated by the HM NIS Edit IO designer. -[Settings] -NumFields=3 -CancelEnabled=0 - -[Field 1] -Type=Groupbox -Text=UNICODE support -Left=8 -Right=292 -Top=0 -Bottom=75 - -[Field 2] -Type=Label -Text=This version of OpenTTD has support for UNICODE, allowing users to use non-ASCII character sets such as Russian or Japanese.\r\nSelecting such a language will result in an unusable and garbled interface. You will need to specify a font that has support for these characters in openttd.cfg, or alternatively use an appropiate grf file.\r\n\r\nFor more information please refer to the readme or the wiki. -Left=13 -Right=284 -Top=9 -Bottom=65 - -[Field 3] -Type=Link -Text=OpenTTD wiki -Left=238 -Right=284 -Top=64 -Bottom=72 -State=http://wiki.openttd.org/index.php/Unicode - diff --git a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp index 6839e922bc..6c07d81038 100644 --- a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp +++ b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp @@ -1110,6 +1110,23 @@ public: case TK_STRING_LITERAL: val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); break; + case '-': + Lex(); + switch(_token) + { + case TK_INTEGER: + val._type = OT_INTEGER; + val._unVal.nInteger = -_lex._nvalue; + break; + case TK_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = -_lex._fvalue; + break; + default: + Error(_SC("scalar expected : integer,float")); + val._type = OT_NULL; // Silent compile-warning + } + break; default: Error(_SC("scalar expected : integer,float or string")); val._type = OT_NULL; // Silent compile-warning diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index baf66af461..4ad1b9374d 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -50,7 +50,9 @@ bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1, res = i1 / i2; break; case '*': res = i1 * i2; break; - case '%': res = i1 % i2; break; + case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } + res = i1 % i2; + break; default: res = 0xDEADBEEF; } trg = res; diff --git a/src/ai/api/ai_abstractlist.cpp b/src/ai/api/ai_abstractlist.cpp index 3fef4d7bc2..b1b9d098d5 100644 --- a/src/ai/api/ai_abstractlist.cpp +++ b/src/ai/api/ai_abstractlist.cpp @@ -375,6 +375,7 @@ AIAbstractList::AIAbstractList() this->sorter_type = SORT_BY_VALUE; this->sort_ascending = false; this->initialized = false; + this->modifications = 0; } AIAbstractList::~AIAbstractList() @@ -389,6 +390,8 @@ bool AIAbstractList::HasItem(int32 item) void AIAbstractList::Clear() { + this->modifications++; + this->items.clear(); this->buckets.clear(); this->sorter->End(); @@ -396,6 +399,8 @@ void AIAbstractList::Clear() void AIAbstractList::AddItem(int32 item) { + this->modifications++; + if (this->HasItem(item)) return; this->items[item] = 0; @@ -404,6 +409,8 @@ void AIAbstractList::AddItem(int32 item) void AIAbstractList::RemoveItem(int32 item) { + this->modifications++; + if (!this->HasItem(item)) return; int32 value = this->GetValue(item); @@ -457,6 +464,8 @@ int32 AIAbstractList::GetValue(int32 item) bool AIAbstractList::SetValue(int32 item, int32 value) { + this->modifications++; + if (!this->HasItem(item)) return false; int32 value_old = this->GetValue(item); @@ -472,6 +481,8 @@ bool AIAbstractList::SetValue(int32 item, int32 value) void AIAbstractList::Sort(SorterType sorter, bool ascending) { + this->modifications++; + if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return; if (sorter == this->sorter_type && ascending == this->sort_ascending) return; @@ -506,6 +517,8 @@ void AIAbstractList::AddList(AIAbstractList *list) void AIAbstractList::RemoveAboveValue(int32 value) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second > value) this->items.erase(iter); @@ -519,6 +532,8 @@ void AIAbstractList::RemoveAboveValue(int32 value) void AIAbstractList::RemoveBelowValue(int32 value) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second < value) this->items.erase(iter); @@ -532,6 +547,8 @@ void AIAbstractList::RemoveBelowValue(int32 value) void AIAbstractList::RemoveBetweenValue(int32 start, int32 end) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second > start && (*iter).second < end) this->items.erase(iter); @@ -545,6 +562,8 @@ void AIAbstractList::RemoveBetweenValue(int32 start, int32 end) void AIAbstractList::RemoveValue(int32 value) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second == value) this->items.erase(iter); @@ -558,6 +577,8 @@ void AIAbstractList::RemoveValue(int32 value) void AIAbstractList::RemoveTop(int32 count) { + this->modifications++; + if (!this->sort_ascending) { this->Sort(this->sorter_type, !this->sort_ascending); this->RemoveBottom(count); @@ -593,6 +614,8 @@ void AIAbstractList::RemoveTop(int32 count) void AIAbstractList::RemoveBottom(int32 count) { + this->modifications++; + if (!this->sort_ascending) { this->Sort(this->sorter_type, !this->sort_ascending); this->RemoveTop(count); @@ -627,6 +650,8 @@ void AIAbstractList::RemoveBottom(int32 count) void AIAbstractList::RemoveList(AIAbstractList *list) { + this->modifications++; + AIAbstractListMap *list_items = &list->items; for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) { this->RemoveItem((*iter).first); @@ -635,6 +660,8 @@ void AIAbstractList::RemoveList(AIAbstractList *list) void AIAbstractList::KeepAboveValue(int32 value) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second <= value) this->items.erase(iter); @@ -648,6 +675,8 @@ void AIAbstractList::KeepAboveValue(int32 value) void AIAbstractList::KeepBelowValue(int32 value) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second >= value) this->items.erase(iter); @@ -661,6 +690,8 @@ void AIAbstractList::KeepBelowValue(int32 value) void AIAbstractList::KeepBetweenValue(int32 start, int32 end) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second <= start || (*iter).second >= end) this->items.erase(iter); @@ -674,6 +705,8 @@ void AIAbstractList::KeepBetweenValue(int32 start, int32 end) void AIAbstractList::KeepValue(int32 value) { + this->modifications++; + for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { next_iter = iter; next_iter++; if ((*iter).second != value) this->items.erase(iter); @@ -687,16 +720,22 @@ void AIAbstractList::KeepValue(int32 value) void AIAbstractList::KeepTop(int32 count) { + this->modifications++; + this->RemoveBottom(this->Count() - count); } void AIAbstractList::KeepBottom(int32 count) { + this->modifications++; + this->RemoveTop(this->Count() - count); } void AIAbstractList::KeepList(AIAbstractList *list) { + this->modifications++; + AIAbstractList tmp; for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { tmp.AddItem((*iter).first); @@ -746,6 +785,8 @@ SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm) SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm) { + this->modifications++; + /* The first parameter is the instance of AIAbstractList. */ int nparam = sq_gettop(vm) - 1; @@ -771,6 +812,10 @@ SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm) /* Walk all items, and query the result */ this->buckets.clear(); + + /* Check for changing of items. */ + int begin_modification_count = this->modifications; + for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { /* Push the root table as instance object, this is what squirrel does for meta-functions. */ sq_pushroottable(vm); @@ -808,6 +853,15 @@ SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm) } } + /* Was something changed? */ + if (begin_modification_count != this->modifications) { + /* See below for explanation. The extra pop is the return value. */ + sq_pop(vm, nparam + 4); + + AIObject::SetAllowDoCommand(backup_allow); + return sq_throwerror(vm, _SC("modifying valuated list outside of valuator function")); + } + (*iter).second = (int32)value; this->buckets[(int32)value].insert((*iter).first); diff --git a/src/ai/api/ai_abstractlist.hpp b/src/ai/api/ai_abstractlist.hpp index 0a8739182c..e0fd4226d4 100644 --- a/src/ai/api/ai_abstractlist.hpp +++ b/src/ai/api/ai_abstractlist.hpp @@ -31,10 +31,11 @@ public: static const bool SORT_DESCENDING = false; private: - AIAbstractListSorter *sorter; - SorterType sorter_type; - bool sort_ascending; - bool initialized; + AIAbstractListSorter *sorter; //!< Sorting algorithm + SorterType sorter_type; //!< Sorting type + bool sort_ascending; //!< Whether to sort ascending or descending + bool initialized; //!< Whether an iteration has been started + int modifications; //!< Number of modification that has been done. To prevent changing data while valuating. public: typedef std::set AIItemList; //!< The list of items inside the bucket @@ -251,6 +252,8 @@ public: * @param valuator_function The function which will be doing the valuation. * @param params The params to give to the valuators (minus the first param, * which is always the index-value we are valuating). + * @note You may not add, remove or change (setting the value of) items while + * valuating. You may also not (re)sort while valuating. * @note You can write your own valuators and use them. Just remember that * the first parameter should be the index-value, and it should return * an integer.