StatusManager.cs
using Sandbox;
using System.ComponentModel;
public struct StatusData
{
public int maxLevel;
public int reqLevel;
public float weight;
public List<string> reqStatuses;
public StatusData( int _maxLevel, int _reqLevel, float _weight, List<string> _reqStatuses = null )
{
maxLevel = _maxLevel;
reqLevel = _reqLevel;
weight = _weight;
reqStatuses = _reqStatuses;
}
}
public class StatusAttribute : Attribute
{
public int MaxLevel { get; }
public int ReqLevel { get; }
public float Weight { get; }
public int MaxDifficulty { get; }
public Type[] ReqStatuses { get; }
public bool IsCurse { get; }
public StatusAttribute( int maxLevel, int reqLevel, float weight, int maxDifficulty, bool isCurse, params Type[] reqStatuses )
{
MaxLevel = maxLevel;
ReqLevel = reqLevel;
Weight = weight;
MaxDifficulty = maxDifficulty;
ReqStatuses = reqStatuses;
IsCurse = isCurse;
}
}
public class StatusManager
{
public static List<TypeDescription> GetRandomStatuses( Player player, int numStatuses, bool curses = false )
{
List<(TypeDescription Type, float Weight)> valid = new List<(TypeDescription, float)>();
var specialistAmount = player.Stats[PlayerStat.SpecialistStatusAmount];
var difficulty = Manager.Instance.Difficulty;
foreach ( var type in TypeLibrary.GetTypes<Status>() )
{
//Log.Info("--------------- " + type.Name);
var attrib = type.GetAttribute<StatusAttribute>();
if ( attrib == null )
{
//Log.Info("not valid - no status attribute!");
continue;
}
if ( player.Level < attrib.ReqLevel )
{
//Log.Info("not valid - ReqLevel is " + attrib.ReqLevel + " and player level is " + player.Level);
continue;
}
var existingLevel = player.GetStatusLevel( type );
if ( existingLevel >= attrib.MaxLevel )
{
//Log.Info("not valid - MaxLevel is " + attrib.MaxLevel + " and player status level is " + player.GetStatusLevel(type));
continue;
}
if ( attrib.ReqStatuses.Length > 0 && attrib.ReqStatuses.All( x => !player.HasStatus( TypeLibrary.GetType( x ) ) ) )
{
//Log.Info("not valid - none of the required statuses owned");
continue;
}
if ( attrib.MaxDifficulty > 0 && difficulty > attrib.MaxDifficulty )
continue;
if ( Manager.Instance.HasSpawnedBoss && type == TypeLibrary.GetType( typeof( EarlyBossStatus ) ) )
continue;
if ( (!curses && attrib.IsCurse) || (curses && !attrib.IsCurse) )
continue;
if ( curses && type == TypeLibrary.GetType( typeof( CurseNumDashesStatus ) ) && (int)player.Stats[PlayerStat.NumDashes] < 2 )
continue;
if ( player.Stats[PlayerStat.NoDashInvuln] > 0f && (type == TypeLibrary.GetType( typeof( NoDashInvulnDamageStatus ) ) || type == TypeLibrary.GetType( typeof( CurseNoDashInvulnDamageStatus ) )) )
continue;
//int currLevel = player.GetStatusLevel(type);
var weight = attrib.Weight;
if ( existingLevel > 0 )
weight += specialistAmount;
//Log.Info( $"valid: adding {type} with weight of " + weight );
valid.Add( (type, weight) );
}
List<TypeDescription> output = new List<TypeDescription>();
// todo: handle if valid has < elements than numStatuses
if ( valid.Count < numStatuses && !curses )
return output;
while ( output.Count < numStatuses )
{
float totalWeight = valid.Sum( x => x.Weight );
var rand = Game.Random.Float( 0f, totalWeight );
//Log.Info("--- output.Count: " + output.Count + " totalWeight: " + totalWeight +" rand: " + rand);
for ( int i = valid.Count - 1; i >= 0; i-- )
{
var (type, weight) = valid[i];
rand -= weight;
//Log.Info("i: " + i + " type: " + type.Name + " weight: " + weight + " rand is now " + rand);
if ( rand < 0f )
{
output.Add( type );
//if( !curses )
valid.Remove( (type, weight) );
break;
}
}
}
return output;
}
public static Status CreateStatus( TypeDescription type )
{
var status = type.Create<Status>();
var attrib = type.GetAttribute<StatusAttribute>();
if ( attrib != null )
status.MaxLevel = attrib.MaxLevel;
else
status.MaxLevel = 1;
return status;
}
//public static Type GetStatusType(string statusName)
//{
// return TypeLibrary.GetDescription(statusName).TargetType;
//}
public static int TypeToIdentity( TypeDescription type )
{
return type.Identity;
}
public static TypeDescription IdentityToType( int typeIdentity )
{
return TypeLibrary.GetTypeByIdent( typeIdentity );
}
}