| Home Page | Recent Changes | Preferences

# AutoLoader

UT2003 :: Actor >> Info >> AutoLoader (Package: ConfigManager)

Here's an /example on how to use this class

    00001  //-----------------------------------------------------------
    00002  //  ConfigManager.AutoLoader
    00003  //
    00004  //  This class has two functions:
    00005  //  1. Perform all required ini changes needed for your mod.  Will also UNDO
    00006  //     any changes made to the ini if your mod is deactivated.
    00007  //     Additional benefit of auto-installation of your mutator on a dedicated
    00008  //     server (to enable set bEnableMyLoader=True in defaultproperties)
    00009  //
    00010  //  2.  Pass FillPlayInfo() calls to mutators which are not part of the game's
    00011  //      mutator list (such as mutators which only require ServerActors= lines in ini)
    00012  //
    00013  //-----------------------------------------------------------
    00014  class AutoLoader extends Info
    00015      abstract;
    00016
    00017  // Quick note about debugging - By setting DEBUG=True in defaultproperties of your
    00018  // AutoLoader subclass when compiling, you can receive large amounts of debug data.
    00019  // However, you will quickly encounter the 1024 byte limit if you use ucc.exe to
    00020  // start the testing server.  By starting a server using the "ut2003 -server" command,
    00021  // you will bypass this limit, since ut2003.exe does not have these limitations.
    00022
    00023  var const bool DEBUG;
    00024  var const bool DEBUGPROPS;
    00025
    00026  var ConfigMaster                Manager;            // Pointer to ConfigMaster mutator
    00027  var string                      InteractionClass;   // Not yet implemented
    00028
    00029  //=======================================
    00030  //  Loading ServerActors
    00031  //=======================================
    00032  // Pointer to GameEngine
    00033  var GameEngine                  GE;
    00034
    00035  // This loader includes a server-side only mutator or server actor
    00036  // that will not be part of the mutator chain (will receive FillPlayInfo() calls)
    00037  var() bool                      bIncludeServerActor;
    00038
    00039  // Classname of the ServerActor this loader loads
    00040  //  Same value as what would otherwise be your mod's
    00041  //  ServerActors= line in the .ini file.
    00042  var() string ActorClass;
    00043
    00044  // Friendly Name of the Server Actor class
    00045  //  Used by webadmin/adminmenu as the name of the server actor
    00046  var() localized string          FriendlyName;
    00047  var() localized string          ActorDescription;
    00048
    00049  // Lock this loader to a certain version (or higher) of your mod
    00050  var() string            RequiredVersion;    // Required version of actor
    00051  var() localized string  VersionWarning;     // Message to write to server log if version not enough
    00052  var() localized string  DownloadMsg;        // Message to write to log
    00053
    00054  //=======================================
    00055  //  Automatic configuration changes
    00056  //=======================================
    00057  // A single ini change
    00058  struct IniEntry
    00059  {
    00060      var() string ClassFrom; // Class which contains the setting we want to change
    00061      var() string PropName;  // Name of the variable we're trying to change
    00062      var() string PropValue; // Value to apply
    00063  };
    00064
    00065  // Array of ini settings required by this mod
    00066  var()   array<IniEntry>                 RequiredIniEntries;
    00067  var     array<Property>                 Properties;
    00068
    00069
    00070  //###################################################################
    00071  //###################################################################
    00072  //
    00073  //  Public methods - should be subclassed to customize loader's response
    00074
    00075  // if return true, loader class will be spawned
    00076  static function bool IsActive()
    00077  {
    00078      return false;
    00079  }
    00080
    00081  // should be subclassed - set loader to active/will be included next match
    00082  static function bool EnableLoader(optional string SpecialActor)
    00083  {
    00084      return false;
    00085  }
    00086
    00087  // should be subclassed
    00088  static function bool DisableLoader(optional string SpecialActor)
    00089  {
    00090      return true;
    00091  }
    00092
    00093  // called on all loader classes - used to activate loader based on active mutators
    00094  static function bool CheckCurrentMutators(string URL)
    00095  {
    00096      return false;
    00097  }
    00098
    00099  // called on all loader classes which have bIncludeServerActor=True - used to activate loader based on manual ServerActor entry
    00100  static function bool CheckStrayActors(string ServerActors)
    00101  {
    00102      local int i;
    00103      local bool bAddMe;
    00104
    00105      if (default.bIncludeServerActor)
    00106          if (InStr(ServerActors,default.ActorClass) != -1)
    00107              bAddMe = EnableLoader();
    00108
    00109      for (i = 0; i < default.RequiredIniEntries.Length; i++)
    00110          if (!bAddMe && default.RequiredIniEntries[i].ClassFrom ~= "Engine.GameEngine" && default.RequiredIniEntries[i].PropName ~= "ServerActors")
    00111              if (InStr(ServerActors,default.RequiredIniEntries[i].PropValue) != -1)
    00112                  bAddMe = EnableLoader();
    00113
    00114      if (default.DEBUG)
    00115      {
    00116          log(default.Class@"Received string value:"$ServerActors,'CheckStrayActors');
    00117          log(default.Class@"Returning"@bAddMe,'CheckStrayActors');
    00118      }
    00119      return bAddMe;
    00120  }
    00121
    00122  // Only managed actors can be added to Ladder profiles
    00123  // Normally, only the ActorClass of your loader (if bIncludeServerActor=True) would be need to be managed
    00124  static function array<string> GetManagedActors()
    00125  {
    00126      local int i;
    00127      local string A, B, C;
    00128      local array<string> ABC;
    00129
    00130      i = -1;
    00131      while (static.AddManagedActor(i++,A,B,C))
    00132          ABC[ABC.Length] = A$","$B$","$C;
    00133
    00134      return ABC;
    00135  }
    00136
    00137  // Managed actors will be passed FillPlayInfo() calls
    00138  static function bool AddManagedActor(int Idx, out string ActorClassName, out string ActorName, out string ActorDesc)
    00139  {
    00140      if (Idx == -1 && default.bIncludeServerActor)
    00141      {
    00142          ActorClassName = default.ActorClass;
    00143          ActorName = default.FriendlyName;
    00144          ActorDesc = default.ActorDescription;
    00145          return true;
    00146      }
    00147
    00148      return false;
    00149  }
    00150
    00151  // Optional hook for version filtering
    00152  static function bool MatchesVersion(float ActorVersion, optional bool bExact, optional string NewURL)
    00153  {
    00154      local float CurrentVersion;
    00155      local string LogText;
    00156
    00157      if (default.RequiredVersion == "")
    00158          return true;
    00159
    00160      CurrentVersion = float(default.RequiredVersion);
    00161
    00162      // Return false if loader version is higher than actor version
    00163      // Return false if loader version is lower than actor version and bExact=True
    00164      if ((ActorVersion < CurrentVersion) || (ActorVersion > CurrentVersion && bExact))
    00165      {
    00166          if (default.VersionWarning != "")
    00167          {
    00168              LogText = static.ReplaceTag(default.VersionWarning,"%CurVer%",CurrentVersion);
    00169              LogText = static.ReplaceTag(LogText,"%ReqVer%",ActorVersion);
    00170              log(LogText);
    00171          }
    00172
    00173          if (NewURL != "")
    00174              log(static.ReplaceTag(default.DownloadMsg,"%URL%",NewURL));
    00175
    00176          return false;
    00177      }
    00178
    00179      return true;
    00180  }
    00181
    00182  // To prevent your loader from causing a server crash, add your checks here
    00183  // return false to prevent your loader from being loaded
    00184
    00185  // You only need to override this function if bIncludeServerActor=False in your loader,
    00186  // or if you have RequiredIniChanges that reference additional custom packages
    00187  static function bool ValidateLoader()
    00188  {
    00189      local class<Info>   MyActor;
    00190
    00191      if (default.bIncludeServerActor && default.ActorClass != "")
    00192      {
    00193          // Specify True for 3rd param in DynamicLoadObject to prevent log spam if MyActor isn't on server
    00194          MyActor = class<Info>(DynamicLoadObject(default.ActorClass,class'Class',True));
    00195          if (MyActor == None)
    00196              return false;
    00197      }
    00198
    00199      return true;
    00200  }
    00201
    00202  // Hook for loader to cancel external removal request, or effect any specialized ini changes to make before removal
    00203  function bool AcceptRemoval(optional array<Property> Props)
    00204  {
    00205      if (Props.Length > 0)
    00206          Properties = Props;
    00207
    00208      RemoveMe();
    00209      return true;
    00210  }
    00211
    00212  // should be subclassed
    00213  // always use "return !bEnableMyLoader;"
    00214  // see LadderLoader.LadderLoader or TeamBalanceLoader.BalanceLoader for examples
    00215  function bool WantsToBeDisabled()
    00216  {
    00217      return false;
    00218  }
    00219
    00220  // called for each RequiredIniEntry
    00221  // return true to apply the RequiredIniEntry.PropValue
    00222  function bool ObjectNeedsUpdate(Object O, string PropName, string PropValue)
    00223  {
    00224      local string Temp;
    00225
    00226      Temp = O.GetPropertyText(PropName);
    00227      if ( InStr(Caps(Temp),Caps(PropValue)) < 0 )
    00228          return true;
    00229
    00230      return false;
    00231  }
    00232
    00233  // notification of pending update - return false to skip update for loader
    00234  function bool ApplyUpdate()
    00235  {
    00236      if (DEBUG) log(class@"Returning"@IsActive(),'ApplyUpdate');
    00237      return IsActive();
    00238  }
    00239
    00240  // return -1 if want to simply add entry
    00241  // return index of array entry if want to overwrite
    00242  function int CheckArrayEntry(string PropName, array<string> PropArray)
    00243  {
    00244      return -1;
    00245  }
    00246
    00247  // To maintain consistency, always add to "Server Actors" page
    00248  // static function FillPlayInfo(PlayInfo PI)
    00249  // {
    00250  //      Super.FillPlayInfo(PI);
    00251  //      PI.AddSetting("ServerActors",....
    00252  // }
    00253  //
    00254  //###################################################################
    00255  //###################################################################
    00256  //
    00257  //  Public Final Methods
    00258  //  These are used to operate the internal mechanisms of the auto loader system.
    00259  //
    00260  //
    00261
    00262  // Called by ConfigMaster when Level.ServerTravel is called
    00263
    00264  // Removes loader if WantsToBeDisabled() returns True
    00265  // Applies value for RequiredIniProperties if ObjectNeedsUpdate returns true
    00266  final function UpdateConfiguration(array<Property> Props)
    00267  {
    00268      local Object            O;
    00269      local Property          P;
    00270
    00271      local string            N,V;
    00272      local int               i, j;
    00273
    00274      local array<string>     Arr;
    00275      local string            ArrS;
    00276
    00277      if (DEBUG)
    00278          log("Update configuration in"@class,'UpdateConfiguration');
    00279
    00280      ResetConfig();
    00281      Properties = Props;
    00282
    00283      if (WantsToBeDisabled())
    00284      {
    00285          RemoveMe();
    00286          return;
    00287      }
    00288
    00289      if (bIncludeServerActor && ActorClass != "")
    00290      {
    00291          O = GetObjectOfClass(class'Engine.GameEngine');
    00292          if (O != None)
    00293          {
    00294              if (ObjectNeedsUpdate(O, "ServerActors", ActorClass))
    00295              {
    00296                  ArrS = O.GetPropertyText("ServerActors");
    00297                  if (ArrS != "")
    00298                      Arr = GenerateArray(ArrS);
    00299
    00300                  j = -1;
    00301                  if (Arr.Length > 0)
    00302                      j = CheckArrayEntry("ServerActors", Arr);
    00303
    00304                  if (j < 0)
    00305                      O.SetPropertyText("ServerActors",AddDynArrayMember(O,"ServerActors",ActorClass));
    00306
    00307                  else O.SetPropertyText("ServerActors",InsertArrayMember(O, "ServerActors", ActorClass, j));
    00308                  O.SaveConfig();
    00309              }
    00310          }
    00311      }
    00312
    00313      for (i = 0;i<RequiredIniEntries.Length;i++)
    00314      {
    00315          O = GetObjectForEntry(RequiredIniEntries[i]);
    00316          if (O == None) continue;
    00317
    00318          if (!ObjectNeedsUpdate(O, RequiredIniEntries[i].PropName, RequiredIniEntries[i].PropValue)) continue;
    00319
    00320          N = RequiredIniEntries[i].PropName;
    00321          V = RequiredIniEntries[i].PropValue;
    00322          P = GetProperty(O, N);
    00323          if (DEBUG)
    00324              log(class@"got property"@p,'UpdateConfiguration');
    00325
    00326          if (P == None) continue;
    00327
    00328          j = -1;
    00329
    00330          if (PropIsArray(P))
    00331          {
    00332              ArrS = O.GetPropertyText(N);
    00333              if (ArrS != "")
    00334                  Arr = GenerateArray(ArrS);
    00335
    00336              if (Arr.Length > 0)
    00337                  j = CheckArrayEntry(N, Arr);
    00338
    00339              if (j < 0)
    00340                  O.SetPropertyText(N,AddDynArrayMember(O,N,V));
    00341
    00342              else O.SetPropertyText(N,InsertArrayMember(O, N, V, j));
    00343          }
    00344
    00345          else
    00346          {
    00347              StoreDefaultValue(O, N);
    00348              O.SetPropertyText(N,V);
    00349          }
    00350
    00351          O.SaveConfig();
    00352      }
    00353  }
    00354
    00355  // Regarding OriginalValues
    00356  final function StoreDefaultValue(Object O, string PropName)
    00357  {
    00358      local int i, idx;
    00359      local IniEntry NewDefault;
    00360      local string CurrentValue, Quote;
    00361      local array<string> Ar;
    00362
    00363      if (DEBUG)
    00364          log(class@"storing default"@o@propname,'StoreDefaultValue');
    00365
    00366      for (i = 0; i < ConfigMaster(Owner).OriginalValues.Length; i++)
    00367          if (ConfigMaster(Owner).OriginalValues[i].ClassFrom == string(O.Class) && ConfigMaster(Owner).OriginalValues[i].PropName == PropName)
    00368              return;
    00369
    00370      NewDefault.ClassFrom = string(O.Class);
    00371      // Check if this property name is a single array member
    00372      i = -1; idx = -1;
    00373      i = InStr(PropName, "§");
    00374      if (i != -1)
    00375      {
    00376          idx = int(Left(PropName, i));
    00377          PropName = Mid(PropName, i + 1);
    00378          CurrentValue = O.GetPropertyText(PropName);
    00379          Ar = GenerateArray(CurrentValue);
    00380          CurrentValue = Ar[idx];
    00381
    00382          // Remove literal string wrapper
    00383          if (Left(CurrentValue,1) == "\"")
    00384          {
    00385              CurrentValue = Mid(CurrentValue,1,Len(CurrentValue) - 2);
    00386              Quote = "¶";
    00387          }
    00388          CurrentValue = idx $ "§" $ CurrentValue $ Quote;
    00389      }
    00390
    00391      else CurrentValue = O.GetPropertyText(PropName);
    00392
    00393      NewDefault.PropName = PropName;
    00394      NewDefault.PropValue = CurrentValue;
    00395      if (DEBUG)
    00396          log(class@"old value:"@NewDefault.PropValue,'StoreDefaultValue');
    00397
    00398      ConfigMaster(Owner).OriginalValues[ConfigMaster(Owner).OriginalValues.Length] = NewDefault;
    00399      ConfigMaster(Owner).SaveConfig();
    00400  }
    00401
    00402  final function bool RestoreOriginalValue(Object O, string PropName)
    00403  {
    00404      local int i, j, idx;
    00405      local string CurrentValue, StoredValue;
    00406      local array<string> Ar;
    00407
    00408      for (i = 0; i < ConfigMaster(Owner).OriginalValues.Length; i++)
    00409      {
    00410          if (ConfigMaster(Owner).OriginalValues[i].ClassFrom ~= string(O.Class) && ConfigMaster(Owner).OriginalValues[i].PropName ~= PropName)
    00411          {
    00412              StoredValue = ConfigMaster(Owner).OriginalValues[i].PropValue;
    00413              // First check if this was a single array member
    00414              j = InStr(StoredValue, "§");
    00415              if (j != -1)
    00416              {
    00417                  idx = int(Left(StoredValue, j));
    00418                  StoredValue = Mid(StoredValue, j + 1);
    00419                  if (Right(StoredValue, 1) == "¶")
    00420                  {
    00421                      StoredValue = Left(StoredValue, Len(StoredValue) - 1);
    00422                      StoredValue = "\"" $ StoredValue $ "\"";
    00423                  }
    00424                  CurrentValue = O.GetPropertyText(PropName);
    00425                  Ar = GenerateArray(CurrentValue);
    00426                  Ar[idx] = StoredValue;
    00427                  StoredValue = "(" $ Join(Ar,",",True) $")";
    00428              }
    00429
    00430              if (DEBUG)
    00431                  log(class@"Assigning"@StoredValue@"to property"@string(O.Class)$"."$PropName,'RestoreOriginalValue');
    00432              O.SetPropertyText(PropName, StoredValue);
    00433              O.SaveConfig();
    00434              break;
    00435          }
    00436      }
    00437
    00438      if (i < ConfigMaster(Owner).OriginalValues.Length)
    00439      {
    00440          ConfigMaster(Owner).OriginalValues.Remove(i, 1);
    00441          ConfigMaster(Owner).SaveConfig();
    00442          return true;
    00443      }
    00444
    00445      return false;
    00446  }
    00447
    00448  //###################################################################
    00449  //###################################################################
    00450  //
    00451  //  Internal Methods
    00452  //  These are used to control the internal operation of the loader itself.
    00453  //  These methods may only be called by other methods within the loader.
    00454  //
    00455
    00456  protected final function RemoveMe()
    00457  {
    00458      local int i;
    00459      local Object O;
    00460      local Property P;
    00461
    00462      if (DEBUG)
    00463          log(class@"being removed.",'RemoveMe');
    00464
    00465      if (bIncludeServerActor && ActorClass != "")
    00466      {
    00467          O = GetObjectOfClass(class'Engine.GameEngine');
    00468          if (O != None)
    00469              RemoveArrayEntry(O, "ServerActors", ActorClass);
    00470      }
    00471
    00472      for (i = 0; i < RequiredIniEntries.Length; i++)
    00473      {
    00474          O = GetObjectForEntry(RequiredIniEntries[i]);
    00475          if (O == None) continue;
    00476
    00477          P = GetProperty(O,RequiredIniEntries[i].PropName);
    00478          if (P != None && PropIsArray(P))
    00479              RemoveArrayEntry(O,RequiredIniEntries[i].PropName,RequiredIniEntries[i].PropValue);
    00480
    00481          else RestoreOriginalValue(O, RequiredIniEntries[i].PropName);
    00482      }
    00483
    00484      DisableLoader();
    00485  }
    00486
    00487  protected final function string InsertArrayMember(Object Obj, string PropName, string NewValue, int Pos)
    00488  {
    00489      local string CurValue, Quote, Tmp;
    00490      local array<string> Members;
    00491      local bool bStatic;
    00492
    00493      if (Obj == None)
    00494      {
    00495          Warn("Object is None");
    00496          return "";
    00497      }
    00498
    00499      CurValue = Obj.GetPropertyText(PropName);
    00500      Members = GenerateArray(CurValue);
    00501
    00502      if (DEBUG)
    00503      {
    00504          log(class$":Inserting new member at position"@Pos@"to"@Obj$"."$PropName$":"@NewValue,'InsertArrayMember');
    00505          log(class$":Current Value:"$CurValue,'InsertArrayMember');
    00506      }
    00507
    00508  // Check for literal string
    00509      if (InStr(Caps(CurValue), Caps(NewValue)) < 0 && Members.Length > 0)
    00510      {
    00511          bStatic = Left(Members[pos], Len(PropName) + 1) ~= (PropName $ "[");
    00512          Tmp = StringIf(bStatic, Mid(Members[pos],InStr(Members[pos],"=") + 1), Members[0]);
    00513          Quote = StringIf(Left(Tmp,1) == "\"" && Left(NewValue,1) != "\"","\"","");
    00514
    00515          NewValue = StringIf(bStatic, PropName $ "=" $ Quote $ NewValue $ Quote, Quote $ NewValue $ Quote);
    00516          if (DEBUG)
    00517              log(InStr(Caps(CurValue),Caps(NewValue))@InStr(Caps(CurValue),Caps(NewValue))<0@Caps(CurValue)@"||"@Caps(NewValue),'AddDynArrayMember');
    00518
    00519          if (NewValue != "" && Pos > -1)
    00520          {
    00521              StoreDefaultValue(Obj, Pos$"§"$PropName);
    00522              Members[Pos] = NewValue;
    00523          }
    00524
    00525          CurValue = "(" $ Join(Members,",",True) $ ")";
    00526      }
    00527
    00528      if (DEBUG)
    00529      {
    00530          log(class@"Returning:"$CurValue,'InsertArrayMember');
    00531          log(class@"",'InsertArrayMember');
    00532      }
    00533
    00534      return CurValue;
    00535  }
    00536
    00537  // Currently, UT2003 does not support setting static arrays through the use of SetPropertyText
    00538  protected final function string AddStaticArrayMember(Object Obj, string PropName, string NewValue)
    00539  {
    00540      local int i;
    00541      local array<string> Members;
    00542      local string Quote, TempValue, CurValue;
    00543
    00544      if (Obj == None)
    00545      {
    00546          Warn("Object was None for property"@PropName);
    00547          return "";
    00548      }
    00549
    00550      CurValue = Obj.GetPropertyText(PropName);
    00551      Members = GenerateArray(CurValue);
    00552
    00553      if (InStr(Caps(CurValue), Caps(NewValue)) < 0)
    00554      {
    00555          if (Members.Length > 0)
    00556          {
    00557              TempValue = Mid(Members[0],InStr(Members[0],"=")+1);
    00558
    00559              // Check for literal string
    00560              Quote = StringIf(Left(TempValue,1) == "\"" && Left(NewValue,1) != "\"", "\"", "");
    00561              for (i = 0; i < Members.Length; i++)
    00562              {
    00563                  if (Members[i] == "")
    00564                  {
    00565                      Members[i] = PropName $ "[" $ i $ "]=" $ Quote $ NewValue $ Quote;
    00566                      break;
    00567                  }
    00568              }
    00569              CurValue = "(" $ Join(Members,",") $")";
    00570          }
    00571
    00572          else CurValue = "(" $ PropName $ "[0]=" $ NewValue $ ")";
    00573      }
    00574
    00575      return CurValue;
    00576  }
    00577
    00578  protected final function string AddDynArrayMember(Object Obj, string PropName, string NewValue)
    00579  {
    00580      local string CurValue, Quote;
    00581      local array<string> Members;
    00582
    00583      if (Obj == None)
    00584      {
    00585          Warn("Object is None");
    00586          return "";
    00587      }
    00588
    00589      CurValue = Obj.GetPropertyText(PropName);
    00590      Members = GenerateArray(CurValue);
    00591      if (DEBUG)
    00592      {
    00593          log(class$":Adding new member to"@Obj$"."$PropName$":"@NewValue,'AddDynArrayMember');
    00594          log(class$":Current Value:"$CurValue,'AddDynArrayMember');
    00595      }
    00596
    00597  // Check for literal string
    00598      if (InStr(Caps(CurValue), Caps(NewValue)) < 0)
    00599      {
    00600          if (Members.Length > 0)
    00601          {
    00602              if (DEBUG)
    00603                  log(InStr(Caps(CurValue),Caps(NewValue))@InStr(Caps(CurValue),Caps(NewValue))<0@Caps(CurValue)@"||"@Caps(NewValue),'AddDynArrayMember');
    00604
    00605              Quote = StringIf(Left(Members[0],1) == "\"" && Left(NewValue,1) != "\"", "\"", "");
    00606              Members[Members.Length] = Quote $ NewValue $ Quote;
    00607              CurValue = "(" $ Join(Members,",",True) $ ")";
    00608          }
    00609          else CurValue = "(" $ NewValue $ ")";
    00610      }
    00611
    00612      if (DEBUG)
    00613      {
    00614          log(class@"Returning:"$CurValue,'AddDynArrayMember');
    00615          log(class@"",'AddDynArrayMember');
    00616      }
    00617
    00618      return CurValue;
    00619  }
    00620
    00621  // UT2003 currently does not support setting the value of static arrays
    00622  protected final function RemoveArrayEntry(Object O, string PropName, string PropValue)
    00623  {
    00624      local int i, j;
    00625      local array<string> Members;
    00626      local string ArrayString, Quote, Tmp;
    00627      local bool bStatic;
    00628
    00629      if (O == None)
    00630      {
    00631          Warn("Object was none for property"@PropName);
    00632          return;
    00633      }
    00634
    00635      ArrayString = O.GetPropertyText(PropName);
    00636      if (ArrayString == "")
    00637      {
    00638          Warn("Property was not found:"@PropName);
    00639          return;
    00640      }
    00641
    00642      if (DEBUG)
    00643      {
    00644          log(class$": Removing array member"@string(O.Class)$"."$PropName$":"$ArrayString,'RemoveArrayEntry');
    00645          log(class$": Member to be removed:"$PropValue,'RemoveArrayEntry');
    00646      }
    00647
    00648      Members = GenerateArray(ArrayString);
    00649      bStatic = Left(Members[0], Len(PropName) + 1) ~= (PropName $ "[");
    00650      Tmp = StringIf(bStatic, Mid(Members[0],InStr(Members[0],"=") + 1), Members[0]);
    00651      Quote = StringIf(Left(Tmp,1) == "\"" && Left(PropValue,1) != "\"","\"","");
    00652
    00653      PropValue = StringIf(bStatic, PropName $ "=" $ Quote $ PropValue $ Quote, Quote $ PropValue $ Quote);
    00654      for (i = 0; i < Members.Length; i++)
    00655      {
    00656          if (DEBUG)
    00657              log(class@"Comparing"@i@PropValue@"to"@Members[i],'RemoveArrayEntry');
    00658
    00659          if (Members[i] ~= PropValue)
    00660              break;
    00661      }
    00662
    00663      if (i < Members.Length)
    00664      {
    00665          if (DEBUG) log(class@"Removing array member"@i$":"$Members[i],'RemoveArrayEntry');
    00666
    00667          // Check if we should restore a previous value
    00668          for (j = 0; j < ConfigMaster(Owner).OriginalValues.Length; j++)
    00669          {
    00670              if (DEBUG)
    00671              {
    00672                  log(class@"Checking Backup Value"@j@"class:"$ConfigMaster(Owner).OriginalValues[j].ClassFrom@"against"@string(O.Class),'RemoveArrayEntry');
    00673                  log(class@"Checking Backup Value"@j@"Property:"$ConfigMaster(Owner).OriginalValues[j].PropName@"against"@PropName,'RemoveArrayEntry');
    00674              }
    00675
    00676              if (ConfigMaster(Owner).OriginalValues[j].ClassFrom ~= string(O.Class) &&
    00677                  ConfigMaster(Owner).OriginalValues[j].PropName ~= PropName )
    00678              {
    00679                  RestoreOriginalValue(O, PropName);
    00680                  break;
    00681              }
    00682          }
    00683
    00684          if (j < ConfigMaster(Owner).OriginalValues.Length)
    00685              return;
    00686
    00687          Members.Remove(i,1);
    00688      }
    00689
    00690      else return;
    00691
    00692      PropValue = "(" $ Join(Members,",") $ ")";
    00693      if (DEBUG)
    00694          log(class@"Assigning"@PropValue@"to property"@string(O.Class)$"."$PropName,'RemoveArrayEntry');
    00695      O.SetPropertyText(PropName,PropValue);
    00696      O.SaveConfig();
    00697      if (DEBUG)
    00698          log(class@"Returning"@O.GetPropertyText(PropName),'RemoveArrayEntry');
    00699  }
    00700
    00701  // Just a function to handle safe object creation
    00702  protected final function Object GetObjectForEntry(IniEntry ThisEntry)
    00703  {
    00704      local Object O;
    00705      local class<Object> OClass;
    00706
    00707      if (DEBUG)
    00708          log(class@"Getting"@ThisEntry.ClassFrom@ThisEntry.PropName@ThisEntry.PropValue,'GetObjectForEntry');
    00709
    00710      OClass = class<Object>(DynamicLoadObject(ThisEntry.ClassFrom,class'Class'));
    00711      if (OClass == None)
    00712      {
    00713          Warn("Could not load class"@ThisEntry.ClassFrom);
    00714          return None;
    00715      }
    00716
    00717      O = GetObjectOfClass(OClass);
    00718      if (O == None)
    00719          Warn("Unable to access object for class"@OClass);
    00720
    00721      return O;
    00722  }
    00723
    00724  protected final function Object GetObjectOfClass(class<Object> ObjClass)
    00725  {
    00726      local Object Obj;
    00727      local Actor A;
    00728
    00729      if (DEBUG)
    00730          log(class@"Finding"@ObjClass,'GetObjectOfClass');
    00731
    00732      // Check for GameEngine
    00733      if (ObjClass == class'GameEngine')
    00734          return GE;
    00735
    00736      // First try the easy way
    00737      foreach AllObjects(ObjClass,Obj)
    00738          return Obj;
    00739
    00740      // Object may not be loaded right now, so attempt to load it
    00741      // If actor, spawn it
    00742      if (ClassIsChildOf(ObjClass,class'Actor'))
    00743      {
    00744          A = Spawn(class<Actor>(ObjClass));
    00745          A.GoToState('');
    00746          return A;
    00747      }
    00748
    00749      // if object, new it
    00750      Obj = new(None) ObjClass;
    00751
    00752      // might be property
    00753      if (Obj == None)
    00754          Obj = new(Class) ObjClass;
    00755
    00756      // Don't know if this will even work ?
    00757      if (Obj == None)
    00758          Obj = New(ObjClass.default.Outer) ObjClass;
    00759
    00760      if (DEBUG)
    00761      {
    00762          log(class@"Could not create new object"@ObjClass,'GetObjectOfClass');
    00763          log(class@ObjClass@"outer is"@ObjClass.default.Outer,'GetObjectOfClass');
    00764          log(class@"",'GetObjectOfClass');
    00765      }
    00766
    00767      return Obj;
    00768  }
    00769
    00770  protected final function Property GetProperty(Object O, string PropName)
    00771  {
    00772      local int i;
    00773      local Class ClassOuter;
    00774      local bool classexact, classchild, propn, seenclass;
    00775
    00776      for (i=0;i<Properties.Length;i++)
    00777      {
    00778          seenclass = Class(Properties[i].Outer) == ClassOuter;
    00779
    00780          ClassOuter = Class(Properties[i].Outer);
    00781          if (DEBUGPROPS)
    00782          {
    00783              if (ClassOuter == None)
    00784              {
    00785                  log(class@"Property Outer is not a class!",'GetProperty');
    00786                  continue;
    00787              }
    00788
    00789              if (!seenclass)
    00790              {
    00791                  log(class@"Compare Obj Class"@O.Class@"to"@Properties[i].Outer,'GetProperty');
    00792                  if (O.Class==Properties[i].Outer)
    00793                      classexact = true;
    00794              }
    00795
    00796              if (!classchild && ClassIsChildOf(O.Class,ClassOuter))
    00797              {
    00798                  log(class@"Obj class"@O.Class@"is child of"@ClassOuter,'GetProperty');
    00799                  classchild = true;
    00800              }
    00801
    00802              else if (!classchild && ClassIsChildOf(ClassOuter,O.Class))
    00803              {
    00804                  log(class@"Obj class"@O.Class@"is parent of"@ClassOuter,'GetProperty');
    00805                  classchild = true;
    00806              }
    00807
    00808              if (!propn && classexact)
    00809              {
    00810                  log(class@"Compare Name"@PropName@"to"@Properties[i].Name,'GetProperty');
    00811                  if (PropName == string(Properties[i].Name))
    00812                      propn = true;
    00813              }
    00814          }
    00815
    00816          if ((ClassIsChildOf(O.Class,ClassOuter)||O.Class == Properties[i].Outer||ClassIsChildOf(ClassOuter,O.Class)) && string(Properties[i].Name) == PropName)
    00817          {
    00818              if (DEBUG)
    00819              {
    00820                  log(class@"Returning Property"@Properties[i],'GetProperty');
    00821                  log(class@"",'GetProperty');
    00822              }
    00823
    00824              return Properties[i];
    00825          }
    00826      }
    00827
    00828      return None;
    00829  }
    00830
    00831  protected final function bool PropIsArray(Property P)
    00832  {
    00833      if (DEBUG)
    00834          log(class@"Checking Property"@P.Outer$"."$P.Name$":"@P.Class,'PropIsArray');
    00835      return P.Class == class'ArrayProperty';
    00836  }
    00837
    00838  protected static final function array<string> GenerateArray(string ArrayString)
    00839  {
    00840      local array<string> Members;
    00841      local int i;
    00842      local string S;
    00843
    00844      if (ArrayString != "")
    00845      {
    00846          // Remove the array wrapper ( )
    00847          ArrayString = Mid(ArrayString,1,Len(ArrayString)-2);
    00848
    00849          // If string contains internal containers, then have to split differently
    00850          if (Left(ArrayString,1) == "(")
    00851          {
    00852              do {
    00853                  do {
    00854                      if (Left(ArrayString,1) == ")")
    00855                          i--;
    00856                      else if (Left(ArrayString,1) == "(")
    00857                          i++;
    00858                      Eat(S, ArrayString, 1);
    00859                  } until (i == 0);
    00860
    00861                  Members[Members.Length] = S;
    00862                  S = "";
    00863                  if (ArrayString != "" && Left(ArrayString,1) == ",")
    00864                      ArrayString = Mid(ArrayString,1);
    00865              } until (ArrayString == "");
    00866          }
    00867
    00868          else Split2(ArrayString,",",Members);
    00869      }
    00870
    00871      return Members;
    00872  }
    00873
    00874  protected static final function bool NotInPlayInfo(PlayInfo PI, class<Info> NewInfo)
    00875  {
    00876      local int i;
    00877      if (PI == None)
    00878      {
    00879          Warn("Invalid PlayInfo Object!");
    00880          return false;
    00881      }
    00882
    00883      for (i=0;i<PI.InfoClasses.Length;i++)
    00884      {
    00885          if (PI.InfoClasses[i] == NewInfo)
    00886              return false;
    00887      }
    00888
    00889      return true;
    00890  }
    00891
    00892
    00893  //###################################################################
    00894  //###################################################################
    00895  //
    00896  //  Utility Methods
    00897  //  These are used perform various tedious operations.
    00898  //
    00899  // Moves Num elements from Source to Dest
    00900  static final function Eat(out string Dest, out string Source, int Num)
    00901  {
    00902      Dest = Dest $ Left(Source, Num);
    00903      Source = Mid(Source, Num);
    00904  }
    00905
    00906  static final function string StringIf(bool Condition, string IfTrue, string IfFalse)
    00907  {
    00908      if (Condition) return IfTrue;
    00909      return IfFalse;
    00910  }
    00911
    00912  // Based on AccessControlIni & Object.ReplaceText()
    00913  static final function string ReplaceTag(string from, string tag, coerce string with)
    00914  {
    00915      local int i;
    00916      local string t;
    00917
    00918      // InStr() is case-sensitive
    00919      i = InStr(Caps(from), Caps(tag));
    00920      while (i != -1)
    00921      {
    00922          t = t $ Left(from,i) $ with;
    00923          from = mid(from,i+len(tag));
    00924          i = InStr(Caps(from), Caps(tag));
    00925      }
    00926
    00927      t = t $ from;
    00928      return t;
    00929  }
    00930
    00931  // Following functions from wUtils103 by El_Muerte[TDS]
    00932  // Included by permission (copied to avoid package dependancy)
    00933
    00934  // Shifts an element off a string
    00935  // example (delim = ' '): 'this is a string' -> 'is a string'
    00936  // if quotechar = " : '"this is" a string' -> 'a string'
    00937  static final function string StrShift(out string line, string delim, optional string quotechar)
    00938  {
    00939      local int delimpos, quotepos;
    00940      local string result;
    00941
    00942      if ( quotechar != "" && Left(line, Len(quotechar)) == quotechar ) {
    00943          do {
    00944              quotepos = InstrFrom(line, quotechar, quotepos + 1);
    00945          } until (quotepos == -1 || quotepos + Len(quotechar) == Len(line)
    00946                  || Mid(line, quotepos + len(quotechar), len(delim)) == delim);
    00947      }
    00948      if ( quotepos != -1 ) {
    00949          delimpos = InstrFrom(line, delim, quotepos);
    00950      }
    00951      else {
    00952          delimpos = Instr(line, delim);
    00953      }
    00954
    00955      if (delimpos == -1)
    00956      {
    00957          result = line;
    00958          line = "";
    00959      }
    00960      else {
    00961          result = Left(line,delimpos);
    00962          line = Mid(line,delimpos+len(delim));
    00963      }
    00964      if ( quotechar != "" && Left(result, Len(quotechar)) == quotechar ) {
    00965        result = Mid(result, Len(quotechar), Len(result)-(Len(quotechar)*2));
    00966      }
    00967      return result;
    00968  }
    00969
    00970  // Join the elements of a string array to an array
    00971  static final function string Join(array< string > ar, optional string delim, optional bool bIgnoreEmpty)
    00972  {
    00973    local string result;
    00974    local int i;
    00975    for (i = 0; i < ar.length; i++)
    00976    {
    00977      if (bIgnoreEmpty && ar[i] == "") continue;
    00978      if (result != "") result = result$delim;
    00979      result = result$ar[i];
    00980    }
    00981
    00982    return result;
    00983  }
    00984
    00985  // Fixed split method
    00986  // no problems when it starts with a delim
    00987  // no problems with ending spaces
    00988  // delim can be a string
    00989  static final function int Split2(coerce string src, string delim, out array<string> parts, optional bool ignoreEmpty, optional string quotechar)
    00990  {
    00991    local string temp;
    00992    Parts.Remove(0, Parts.Length);
    00993    if (delim == "" || Src == "" ) return 0;
    00994    while (src != "")
    00995    {
    00996      temp = StrShift(src, delim, quotechar);
    00997      if (temp == "")
    00998      {
    00999        if (!ignoreEmpty)
    01000        {
    01001          parts.length = parts.length+1;
    01002          parts[parts.length-1] = temp;
    01003        }
    01004      }
    01005      else {
    01006        parts.length = parts.length+1;
    01007        parts[parts.length-1] = temp;
    01008      }
    01009    }
    01010    return parts.length;
    01011  }
    01012
    01013  // InStr starting from an offset
    01014  static final function int InStrFrom(coerce string StrText, coerce string StrPart, optional int OffsetStart)
    01015  {
    01016    local int OffsetPart;
    01017
    01018    OffsetPart = InStr(Mid(StrText, OffsetStart), StrPart);
    01019    if (OffsetPart >= 0)
    01020      OffsetPart += OffsetStart;
    01021    return OffsetPart;
    01022  }

Wormbo: Hmm, a little documentation instead of the source code wouldn't hurt. E.g. how can you use this to enable/disable a server actor?

El Muerte TDS: like this: [ChatFilter AutoLoader], maybe write a [/example] based on it... first lunch

Category Class (UT2003)
Category Custom Class

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In