Sorthious

Member
I'm trying to fix some errors I found in a script from RunUO....Cursed Pirates...here is a link to the page

http://www.runuo.com/community/threads/cursed-pirates-and-artifacts.60932/
Here is what I've done so far....sorry lots of notes and me stumbling around. Fairly new to C# and scripting. I want to find a way, basically to have it check if player is Dead when it hits OnTick() and if dead or Blessed(immortal) then have it wait like a minute and check again. I'm totally lossed on this and any help would be appreciated...thanks in advance!

Code:
sing System;
using System.Collections;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Scripts;

namespace Server.Items
{
   public abstract class PirateCurse
   {

  public static void CursedPirateLoot(BaseCreature pirate, int chance)
  {
  switch (Utility.Random(chance))
  {
  case 0: pirate.PackItem(new CursedJugOfRum()); break;
  }
  }

     public static void SummonPirate( Mobile m, int i_type )
     {
       Map map = m.Map;
       if (map == null)
         return;

       bool validLocation = false;
       Point3D loc = m.Location;

       for (int j = 0; !validLocation && j < 10; ++j)
       {
         int x = loc.X + Utility.Random(3) - 1;
         int y = loc.Y + Utility.Random(3) - 1;
         int z = map.GetAverageZ(x, y);

         if (validLocation = map.CanFit(x, y, loc.Z, 16, false, false))
           loc = new Point3D(x, y, loc.Z);
         else if (validLocation = map.CanFit(x, y, z, 16, false, false))
           loc = new Point3D(x, y, z);
       }

       if (!validLocation)
         return;

       BaseCreature spawn;

       switch ( i_type )
         {
         default: return;
         case 0:
         {
           m.SendMessage("You have summoned a cursed pirate!");

           spawn = new CursedPirate();
           break;
         }
         case 1:
         {
           m.SendMessage("Uh oh, you have summoned the cursed pirate king");

           spawn = new CursedPirateKing();
           break;
         }
       }

       spawn.FightMode = FightMode.Closest;

       spawn.MoveToWorld( loc, map );
       spawn.Combatant = m;
     }

     public static void HurtPlayer(Mobile m)
     {
       m.SendMessage("Ouch, that hurts");

       AOS.Damage(m, m, Utility.RandomMinMax(30, 150), 0, 100, 0, 0, 0);

       if (m.Alive && m.Body.IsHuman && !m.Mounted)
         m.Animate(20, 7, 1, true, false, 0); // take hit
     }

  //was static
     public static void CursePlayer(Mobile m)
     {
       if (IsCursed(m))
         return;

       if (!UnEquipPlayer(m))
         return;

       ExpireTimer timer = (ExpireTimer)m_Table[m];

       if (timer != null)
         timer.DoExpire();
       else
         m.SendMessage("You feel yourself transform into a cursed pirate");

       Effects.SendLocationEffect(m.Location, m.Map, 0x3709, 28, 10, 0x1D3, 5);



  TimeSpan duration = TimeSpan.FromSeconds(240.0);

  //replaced duration with the following:
  //_pirateCurseRemainingDuration = DateTime.Now + TimeSpan.FromSeconds(240);

       ResistanceMod[] mods = new ResistanceMod[4]
       {
         new ResistanceMod( ResistanceType.Fire, -10 ),
         new ResistanceMod( ResistanceType.Poison, -10 ),
         new ResistanceMod( ResistanceType.Cold, +10 ),
         new ResistanceMod( ResistanceType.Physical, +10 )
       };

  timer = new ExpireTimer(m, mods, duration);
  timer.Start();

  m_Table[m] = timer;

       for (int i = 0; i < mods.Length; ++i)
         m.AddResistanceMod(mods[i]);

       m.ApplyPoison(m, Poison.Greater);

       m.Criminal = true;
     }

     public static bool IsCursed(Mobile m)
     {
       BankBox bankBox = m.BankBox;

  Console.WriteLine("Bank MaxItems at time of IsCurseCheck = {0}", m.BankBox.MaxItems);

       if (bankBox == null)
  {
  Console.WriteLine("IsCursed() and BankBox = null");
  return false;
  }

       Item piratebag = bankBox.FindItemByType(typeof(PirateBag));
       if (piratebag == null)
  {
  Console.WriteLine("PirateBag is null in IsCursed");
  return false;
  }

       m.SendMessage("You are already under the effects of the pirate curse!");
       return true;
     }

     public static bool UnEquipPlayer(Mobile m)
     {
       ArrayList ItemsToMove = new ArrayList();

       PirateBag pirateBag = new PirateBag();
  
       BankBox bankBox = m.BankBox;  
  
  //removed following due to players with full banks
  //|| !bankBox.TryDropItem(m, bag, false)
       if (bankBox == null )
       {
  Console.WriteLine("BankBox is null in UnEquipPlayer");
  pirateBag.Delete();
         return false;
       }
       else
       {
  Console.WriteLine("Bank MaxItems before adjustments = {0}",m.BankBox.MaxItems);
  Console.WriteLine("Backpack MaxItems before adjustments = {0}", m.Backpack.MaxItems);

  pirateBag.Owner = m;
  pirateBag.PlayerTitle = m.Title;
  pirateBag.PlayerHue = m.Hue;
  //keep track of MaxItems for Bank/Backpack
  pirateBag.PlayerBankMaxItems = m.BankBox.MaxItems;
  pirateBag.PlayerBackpackMaxItems = m.Backpack.MaxItems;

  //increase bank max items temp to accomodate items
  // include TotalItems incase bank is already over cap
  //from Holliday Gift Boxes and other stuff
  m.BankBox.MaxItems = m.BankBox.TotalItems + 1;
  m.BankBox.AddItem(pirateBag);  
  
         foreach (Item item in m.Items)
           if (item.Layer != Layer.Bank && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && item.Layer != Layer.Mount && item.Layer != Layer.Backpack)
             ItemsToMove.Add(item);  

  foreach (Item item in ItemsToMove)
  {
  //increase bank MaxITems for each item in bag
  m.BankBox.MaxItems += 1; ;
  pirateBag.AddItem(item);
  }
  Console.WriteLine("Done adding items to PirateBag in UnequipPlayer");

         m.Title = "the Cursed Pirate";
         m.Hue = Utility.RandomMinMax(0x8596, 0x8599);

         EquipPirateItems(m);
       }
  Console.WriteLine("Returning true in UnequipPlayer");
  Console.WriteLine("Bank MaxItems = {0}", m.BankBox.MaxItems);

       return true;
     }

     private static void EquipPirateItems(Mobile player)
     {
       //Equip the cursed pirate garb.
       //Cutlass
       Cutlass cutlass = new Cutlass();
       cutlass.Movable = false;
       cutlass.Skill = SkillName.Swords;
       cutlass.Layer = Layer.OneHanded;
       player.AddItem(cutlass);

       //Fancy Shirt
       FancyShirt shirt = new FancyShirt(Utility.RandomNeutralHue());
       shirt.Movable = false;
       player.AddItem(shirt);

       //Long Pants
       LongPants pants = new LongPants(Utility.RandomNeutralHue());
       pants.Movable = false;
       player.AddItem(pants);

       //Tricorne Hat
       TricorneHat hat = new TricorneHat(Utility.RandomNeutralHue());
       hat.Movable = false;
       player.AddItem(hat);

       //Thigh Boots
       ThighBoots boots = new ThighBoots();
       boots.Movable = false;
       player.AddItem(boots);
     }

     public static bool UnequipPirateItems(Mobile m)
     {
       ArrayList ItemsToMove = new ArrayList();
       ArrayList ItemsToDelete = new ArrayList();

       Bag deletePirateGearBag = new Bag();
       BankBox bankBox = m.BankBox;
  
  //removed this from check because players with
  //full bank boxes would not be cursed
  //|| !bankBox.TryDropItem(m, bag, false)||
       if (bankBox == null )
       {
  deletePirateGearBag.Delete();
         return false;
       }
  else
  {
  bankBox.MaxItems = bankBox.TotalItems > bankBox.MaxItems ?
  bankBox.TotalItems + 1 : bankBox.MaxItems + 1;
  bankBox.AddItem(deletePirateGearBag);
  }

       Bag playerUnequippedItems = new Bag();
  playerUnequippedItems.Name = "Pirate Curse Unequiped Items";
  playerUnequippedItems.Hue = m.Hue;

       Container pack = m.Backpack;
  //cut these for same reason as previously
  //&& !pack.CheckHold( m, bag2, false, true )
       if ( pack == null )
       {
  playerUnequippedItems.Delete();
         return false;
       }
  //temp increase backpack storage to accomodate xfer
  pack.MaxItems = pack.TotalItems > pack.MaxItems ?
  pack.TotalItems + 1 : pack.MaxItems + 1;

  pack.AddItem(playerUnequippedItems);

       foreach (Item item in m.Items)
       {
         if (item.Layer != Layer.Bank && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && item.Layer != Layer.Mount && item.Layer != Layer.Backpack)
         {
           if (item.Layer == Layer.OneHanded || item.Layer == Layer.Shirt || item.Layer == Layer.Pants || item.Layer == Layer.Helm || item.Layer == Layer.Shoes )
             ItemsToDelete.Add(item);
           else
             ItemsToMove.Add(item);
         }
       }

       foreach (Item item in ItemsToDelete)
  deletePirateGearBag.AddItem(item);
  deletePirateGearBag.Delete();
  //need something here to account for increase to players

  foreach (Item item in ItemsToMove)
  {
  //increase pack max items temp to accomodate items
  pack.MaxItems = pack.TotalItems > pack.MaxItems ?
  pack.TotalItems + 1 : pack.MaxItems + 1;
  playerUnequippedItems.AddItem(item);
  }

       RestorePlayerItems(m);

       return true;
     }

     public static bool RestorePlayerItems(Mobile player)
     {
       ArrayList ItemsToEquip = new ArrayList();

       BankBox bankBox = player.BankBox;
       if ( bankBox == null )
         return false;

       PirateBag pirateBag = (PirateBag)bankBox.FindItemByType( typeof( PirateBag ));

  if (pirateBag == null)
  {
  Console.WriteLine("Returning false in RestorePlayerItems: Piratebag = null");
  return false;
  }

  //PirateBag piratebag = bag as PirateBag;
       foreach (Item item in pirateBag.Items)
         ItemsToEquip.Add(item);

  foreach (Item item in ItemsToEquip)
  {
  player.AddItem(item);
  }
  Console.WriteLine("Finished adding items to player in RestorePlayerItems");

  player.Title = pirateBag.PlayerTitle;
  player.Hue = pirateBag.PlayerHue;
  //reset containers MaxItems
  player.BankBox.MaxItems = pirateBag.PlayerBankMaxItems;
  player.Backpack.MaxItems = pirateBag.PlayerBackpackMaxItems;

  pirateBag.Delete();
  

  Console.WriteLine("Bank MaxItems = {0}", player.BankBox.MaxItems);
  Console.WriteLine("Backpack MaxItems = {0}", player.Backpack.MaxItems);

       return true;
     }

  private static Hashtable m_Table = new Hashtable();

  //why is there a bool returned???
     public static bool RemoveCurse(Mobile m)
     {
  ExpireTimer t = (ExpireTimer)m_Table[m];

  if (t == null)
  return false;

  //place If Alive check here and extend DelayCall?
  while (!m.Alive)
  {
  
  }
  
  m.SendMessage("The effects of the pirate curse have been removed");
  t.DoExpire();
  
  
  
       return true;
     }

     private class ExpireTimer : Timer
     {
       private Mobile m_Mobile;
       private ResistanceMod[] m_Mods;


  private DateTime _pirateCurseRemainingDuration;

  public DateTime PirateCurseRemainingDuration
  {
  get { return _pirateCurseRemainingDuration; }
  set { _pirateCurseRemainingDuration = value; }
  }

       public ExpireTimer(Mobile m, ResistanceMod[] mods, TimeSpan delay):base(delay)
       {
         m_Mobile = m;
         m_Mods = mods;
  PirateCurseRemainingDuration = DateTime.Now + TimeSpan.FromMinutes(1);
       }

       public void DoExpire()
       {

  UnequipPirateItems(m_Mobile);

  for (int i = 0; i < m_Mods.Length; ++i)
  m_Mobile.RemoveResistanceMod(m_Mods[i]);

  if (m_Mobile.Criminal)
  m_Mobile.Criminal = false;
  if (m_Mobile.Poisoned)
  m_Mobile.CurePoison(m_Mobile);

  Stop();
  m_Table.Remove(m_Mobile);  
       }

       protected override void OnTick()
       {
  while( !m_Mobile.Alive  || !m_Mobile.Blessed)
  {
  Timer.DelayCall(TimeSpan.FromMinutes(1.0),OnTick);
  m_Mobile.SendMessage("The pirates curse endures, even in death!");
  
  }
  
  m_Mobile.SendMessage("You feel the effects of the pirate curse wear off");
  DoExpire();  
       }

  
     }
   }
}
 
Also, I should mention for those that use the Cursed Pirates scripts..There are several isues with it. The script, as it was, wouldnt 'Curse' a player that has a full bank box or similar issue with backpack. If you do a reboot the timer is cancelled and the player never has their gear/hue returned. Trying to fix this up and will post fix when done.
 
For starters, line 416 you want an IF not a WHILE, since you don't want the code inside that condition to continue executing, you just want to check its instantaneous state.

The bug related to the timer being "canceled" when the server reboots indicates that it isn't being serialized or deserialized. So the m_Table that indicates who is currently cursed is simply re-instantiated fresh and empty.

A few ways you can accomplish that, the easiest way that leaps to mind is to create some item that sits in the world as an anchor for serialization, then you have an initilize() section in the pirate curse class that populates its internal static m_Table from the freshly deserialized "PirateCurseController"
 
Last edited:
Tyvm for response...still new to C# and programming in general so bit of greek to me. I think I need to study how to use timers more. Also, I may be going around it the wrong way. A lot of stuff in above script is me thinking by typing crap out lol. I'm basically looking for a way to hold off exuction of DoExpire() till player is alive again. I think I understand the part about saving the timer. Not even sure if that is the best method to go about doing what I'm trying to do. Anway, could you possibly point me to a good resource or script in UO that does what I'm trying to do? I don't mind researching/learning on my own. But I coudln't find what I was looking for. Anyway, thanks again for the reply!
 
Well I think the question may be why you want to wait for them to be alive again to revert it, I would suspect the ideal scenerio is an OnBeforeDeath that reverts it the instant before they die, such that their corpse is normal again.
 
I wanted to make sure they were under influence of the curse for a full 4mins(which is how the original script has it.) If they happend to die before the timer expired I wanted to continue waiting till they were alive again. Anyway, I figured out how to wait till they are alive. Here is what I have in my ExpireTimer Class. I'm stuck again though. Not sure how to serialize/deserialize this:

Code:
  private static Hashtable m_Table = new Hashtable();

     private class ExpireTimer : Timer
     {
       private Mobile m_Mobile;
       private ResistanceMod[] m_Mods;


       public ExpireTimer(Mobile m, ResistanceMod[] mods, TimeSpan delay,
  TimeSpan delay2):base(delay, delay2)
       {
         m_Mobile = m;
         m_Mods = mods;

       }

       public void DoExpire()
       {

  UnequipPirateItems(m_Mobile);

  for (int i = 0; i < m_Mods.Length; ++i)
  m_Mobile.RemoveResistanceMod(m_Mods[i]);

  if (m_Mobile.Criminal)
  m_Mobile.Criminal = false;
  if (m_Mobile.Poisoned)
  m_Mobile.CurePoison(m_Mobile);

  this.Stop();
  m_Table.Remove(m_Mobile);   
       }

       protected override void OnTick()
       {

  if (!m_Mobile.Alive)
  {

  if (m_Mobile.Alive)
  {
  DoExpire();
  }
  }
  else
  {
  m_Mobile.SendMessage("You feel the effects of the pirate curse wear off");
  DoExpire();
  }
       }
     }
 
So, There are three ways that immediately jump to mind.

  1. You can store these details in an individually attached object, an XmlAttachment for example, or simply creating an item which will store the values for you.
  2. You can store these details on the targeted playermobile, adding an additional step to serialization and increment the version. (If you are entirely unfamiliar with how serialization/deserialization works this is not advisible.)
  3. You can store these details in a universal "Controller" object, instantiated in the world somewhere and then accessed in initialization.

The specific details you want to save are A. the Mobile it's attached to B. The referenced resistance mods, and C. the datetime it will expire. When it's deserialized you'll create a new timer (since the timer will not have been serialized hence the entire issue) on the target mobile expiring at the designated datetime.
 
The HashTable m_table stores ExpireTimer which stores Mobile,MOds and Delay.....Can I serialize it and restart timer in deserialize? If so, how?? Sorry I'm such a noob at programming...been reading about timers and ser/des but not seen anything about how to deserialize a HashTable. Don't really need to increment a version, if I understood what I read correctly, as none of the Classes in the Pirate Curse script serializes anything.
 
You wouldn't want to serialize timer, instead you'd likely want to convert whatever remaining from the timer in say something like seconds (or milliseconds) and save that as an int, then when you load you'd start the timer again with the loaded value.
 
The point here is not to serialize/deserialize the timer itself, only the details that you nede to resume the timer after restarting.
 
Thats where I'm stuck lol....I could put the remaining time into a variable if I knew how and where in the script to retrieve it. Also, I'm not sure how to restart the timer from Deserialize. I've been looking on RunUO and here but I can't find tutorial/example of what I'm trying to do. Any pointers would be appreciated.
 
https://github.com/ServUO/ServUO/blob/master/Server/Timer.cs
Is the class your timer is based on. Your timer is an object itself so you'd reference the variable "Next" of the timer, it signals when the next tick should be. You can then do some math with DateTime.Now for the difference and that would be the duration left. The hashtable is not linked to the save system however so I can't express with what I see here where you could actually save this information. You could write a simple save operation yourself and hook into the onload and onsave methods to write your own file for this, but that would require some work itself seeing as you would need to be sure the mobiles where loaded before you tried to load the save.
 
Thats where I'm stuck lol....I could put the remaining time into a variable if I knew how and where in the script to retrieve it. Also, I'm not sure how to restart the timer from Deserialize. I've been looking on RunUO and here but I can't find tutorial/example of what I'm trying to do. Any pointers would be appreciated.

If you need an example of how to Serialize/Deserialize the time left in a timer, here's how I do it the item WebCenter:

This code works with original RunUO, but with ServUO I would try to compute the number of ticks as a double instead of using DeltaTime.

Code:
    private class WebCenter : Item
     {
       private Timer m_Timer;
       private DateTime m_End;
       private Mobile m_Caster;

      
       public WebCenter( Point3D loc, Map map, Mobile caster, int ItemNumber ) : base( ItemNumber )
       {
         TimeSpan duration = TimeSpan.FromSeconds( 15.0 );
         TimeSpan interval = TimeSpan.FromSeconds( 15.0 );
         m_Caster = caster;
         m_Timer = new InternalTimer( m_Caster, this, duration, interval, 4 );
         m_Timer.Start();
        
         m_End = DateTime.Now + TimeSpan.FromSeconds( 60.0 );
       }
      
       public WebCenter( Serial serial ) : base( serial )
       {
       }
      
       public override void Serialize( GenericWriter writer )
       {
         base.Serialize( writer );
        
         writer.Write( (int) 0 ); // version
        
         writer.WriteDeltaTime( m_End );
         writer.Write( (Mobile)m_Caster );
       }
      
       public override void Deserialize( GenericReader reader )
       {
         base.Deserialize( reader );
        
         int version = reader.ReadInt();
        
         switch ( version )
         {
           case 0:
           {
             m_End = reader.ReadDeltaTime();
             m_Caster = (Mobile)reader.ReadMobile();
            
             m_Timer = new InternalTimer( m_Caster, this, m_End - DateTime.Now, TimeSpan.FromSeconds( 15 ), 1);
             m_Timer.Start();
            
             break;
           }
         }
       }
      
       private class InternalTimer : Timer
       {
         private WebCenter m_Item;
         private int counter;
         private int endcount;
         private Mobile m_Caster;
        
         public InternalTimer( Mobile caster, WebCenter item, TimeSpan duration, TimeSpan interval, int count ) : base( duration, interval, count )
         {
           m_Caster = caster;
           Priority = TimerPriority.OneSecond;
           m_Item = item;
           counter = 0;
           endcount = count;
         }
        
         protected override void OnTick()
         {
           // do stuff
         }  
       }
     }
 
Awesome!!...thank you both for the resources! I actually figured out how to serialize the _endTime, and an interval that I use to repeat the timer if the player is dead(_checkAliveWait). But (as per usual) I'm stuck again LOL. I was trying to serialize the _mods(Type ResistanceMod) in the script but ResitanceMods doesn't have a Serialize set up for it. Or I'm totally not understanding how to do it.

Code:
writer.Write( (int) _mods.Length );
   
  for (int i = 0; i < _mods.Length; i++)
  {
  _mods[i].Serialize(writer);
   
  }

This tells me that there is no definition for Serialize in ResistanceMod...anyway back to research see if i can figure this part out.
 
the _mods class type has no definition for serialize, It however seems you already have something serializing so instead of passing the writer you could save the needed parts of _mods and create a new <type> with the deserialized values and apply when loading.
 
Nah...that ser doesnt work....I'm trying a List now ....it's gonna work one way or the other!! I'm finding some more stuff on RunUO ..learning a good bit but still stuck. _mods holds ResistanceMod(type,offset) but not sure how to extract it from _mods or save the individual parts. I'm tinkering with things now and learning in the process.

I am trying to write list and I don't understand the last parm:

Code:
writer.WriteList<ResistanceMod>(_mods,Action<ResistanceMod> onSerialize);

dunno what is supposed to go int the Action<ResistanceMod> onSerialize section
 
After reading through the serialization method for mobile and all references to ResistanceMod, I don't believe resistance mods are serialized.

Which means there's no point to tracking them after deserialization, you'll just re-apply them fresh when the timer itself gets deserialized.

So all you need to serialize is the Mobile and the TimeRemaining.
 
I think I understand...I was going to add a Bool into the CursePlayer part called _isModded. Then in Deserialize if _isModded == true then add the 4 mods back into _mods list. I set up a seperate Method to add the Mods to the "_mods" list. So, if I understand this then I could add the _mods list back and then restart the timer(which would remove the mods when the timer was done correct?

I was reading something about types that were not Items/Mobiles or Primitive Types and that you had to create Custom serializers for them. Thats way beyond me at the moment. Thank you for continuing to respond...I feel like a total idiot for not being able to figure this out!! I'll get there sooner or later though:cool:
 
Items and Mobiles are the 2 classes that easily use the save to serialize themselves, anything based on them also uses the same to save and load. There are a few other things that save and load like accounts and guilds and what not but they aren't as easy to get to. It's actually not too hard to write information to files, or load the files so custom serialization is doable, just take a look at tutorials for C# read/write functions (In/Out) and you'll see how to create your own files. It's also easy with the event handlers to have the server run method of your creation on load/save, then in those methods you'd write/read your file.

If you want a script that shows a decent way to do this, and know the XML file formating you can check my book publisher script, http://www.servuo.com/archive/player-book-publishing-system.341/ it has a custom save and load so that all publishers get the same listing of published books.
 
Rock on!! Thanks so much...I think this is exactly what I'm looking for. Been watching videos on serialization and think I'm getting the hang of it. Probably gonna still take me a bit to get this down but at least now I know where to look!
 
I gave up on the idea of trying to customize use a custom serialization. I did find a fix to the problems without doing it. Thanks so much for the help. Oh, and the orignal scripts were written by Dracana....so props to him for a cool idea! I posted the fixes on RunUO. My post is at the bottom of the page...Here is the link:

http://www.runuo.com/community/threads/cursed-pirates-and-artifacts.60932/page-2

Can someone tell me why I can't upload Archives or .CS files to ServUO? I can upload images just not other files. I would like to post the fixed Pirate Curse Collection in RunUO resources but it won't let me . Anyway, thank you all again for the help!
 
Last edited:
Did you try to rar the file up and then post it? Let's ask @dmurphy :)
Maybe the privileges need to be fixed for that forum
 
Last edited:
It worked...dunno why the other file formats don't work...they are listed in the FileTypes list but it doesnt show any of those file types as selectable, only RAR's.
 
Hmm that is an odd one. I have checked and the file types are indeed allowable. I will look into it though and see if I can figure it out.
 
In the Right-FileType box...it lists all the types...but in the main File window none of the Archived File types are displayed to select. Huh??!! Now it is working! Does the server auto-log for inactivity? Maybe something like that had happened.
 
When you try to upload .cs files it does not show the file in the main window, but when you start typing the name of the file, it will show as a suggestion below your typing, and it actually lets you upload it. It's strange, but it works.
 
I did notice that if I stay inactive for a while on here it logs me without informing me, so I think my issue was it allowed me to us the UploadAFile button while I wasn't logged and thus, wouldn't allow the upload. But oddly, it did show the files with .txt and .png,bmp,etc. Good to know about the .cs files though, thanks!
 

Active Shards

Donations

Total amount
$0.00
Goal
$1,000.00
Back