//-----prepare command database
BonkerBox_C.DBAddCommandRacer(BonkerBox_FWEnvi.GetSkinName(), "fw")

BonkerBox_C.DBAddCommand(
BonkerBox_FWEnvi.GetSkinName(),
"bodycount",
BonkerBox_C.GenCommandInfo("Alter the number of body segments one's Fuzzy Wiggler is using. This value has a hard cap to prevent stressing both rendering and netgame logic so the number of body segments one's Fuzzy Wiggler appears to have may end up less than the value entered for this argument.",{["count"]={["typecode"]=1,["desc"]="How many body parts to give to one's Fuzzy Wiggler? This value is, of course, limited by the overruling cap dictated by the value of ‘bodycap’."}}),
false)

BonkerBox_C.DBAddCommand(
BonkerBox_FWEnvi.GetSkinName(),
"ghost",
BonkerBox_C.GenCommandInfo("Make all Fuzzy Wiggler body segments in the server appear as though ghosts to improve visibility & clarify collision for other racers going up against Fuzzy Wiggler. "..BonkerBox_C.GetReplayNotif(),{["value"]={["typecode"]=2,["desc"]=BonkerBox_C.GetDuhDesc()}}),
true)

BonkerBox_C.DBAddCommand(
BonkerBox_FWEnvi.GetSkinName(),
"bodycap",
BonkerBox_C.GenCommandInfo("Change the value of the hard-cap for the 'bodycount' argument. No refunds on one's server crashing if one sets this too high! "..BonkerBox_C.GetReplayNotif(),{["value"]={["typecode"]=1,["desc"]=BonkerBox_C.GetDuhDesc()}}),
true)

local acc = BonkerBox_FWEnvi.GetAltColourCount()

for i=1,acc
	local cmdname = BonkerBox_FWEnvi.GetAltColourName(i)
	
	BonkerBox_C.DBAddCommand(
	BonkerBox_FWEnvi.GetSkinName(),
	cmdname,
	BonkerBox_C.GenCommandInfo("Modify the colour of one's Fuzzy Wiggler from the head to the rear according to 'bodycolmapping'.",{["col"]={["typecode"]=3,["desc"]="The name of a colour that each affected body segment will turn."}}),
	false)
end

BonkerBox_C.DBAddCommand(
BonkerBox_FWEnvi.GetSkinName(),
"bodycolspeed",
BonkerBox_C.GenCommandInfo("Animate the colours of one's Fuzzy Wiggler by shifting the affected body segments by this abstract rate over time.",{["speed"]={["typecode"]=1,["desc"]="How fast the animation should play. Input a negative number to reverse the animation!"}}),
false)

BonkerBox_C.DBAddCommand(
BonkerBox_FWEnvi.GetSkinName(),
"bodycolmapping",
BonkerBox_C.GenCommandInfo("How the 'bodycol' Fuzzy Wiggler console variables will map to the wiggler.",{["mode"]={["typecode"]=4,["desc"]="Which mapping mode to pick.\nThere's mapping mode '"..BonkerBox_FWEnvi.GetMappingModeEnumByIndex(1,false).."' which will set every nth body segment to the colour associated with the 'n' part of the 'bodycol' command.\nThere's mapping mode '"..BonkerBox_FWEnvi.GetMappingModeEnumByIndex(2,false).."' which will loop the body colours according to how many body colours are settable ("..(BonkerBox_FWEnvi.GetAltColourCount()+1)..").\nAny other mapping mode either doesn't exist or is undocumented."}}),
false)

//-----generate commands
//anything that is a CV_RegisterVar() (doesn't cache to player objects) should be considered a 'live' effect i.e. replays are fine with it being altered during playback
//anything that is COM_AddCommand() (does cache to player objects) should be considered a 'recorded' effect i.e. replays expect it to be unaltered during playback

local cvar_ghostbody = CV_RegisterVar({
	name = BonkerBox_C.GenCommandName(BonkerBox_FWEnvi.GetSkinName(),"ghost"),
	defaultvalue = 0,
	flags = CV_NETVAR,//not only will CV_NETVAR auto-sync the value of the variable, it'll also make it so that only admins and hosts can change it just like i want. lucky!
	PossibleValue = CV_OnOff,
	func = nil//only needs to be set if flag CV_CALL is present
})

local cvar_bodycap = CV_RegisterVar({
	name = BonkerBox_C.GenCommandName(BonkerBox_FWEnvi.GetSkinName(),"bodycap"),
	defaultvalue = 10,
	flags = CV_NETVAR|CV_CALL,
	PossibleValue = CV_Unsigned,
	func = function(cvar) for p in players.iterate if(BonkerBox_G.IsPlayingAs(p, BonkerBox_FWEnvi.GetSkinName() )==true) BonkerBox_FWMain.ShutDown(p) end end end
})

//this is a command and not a cvar because net-synced cvars are only editable by admins and storing numbers in a mobj automatically syncs as a replacement
COM_AddCommand(BonkerBox_C.GenCommandName(BonkerBox_FWEnvi.GetSkinName(),"bodycount"),function(player,count)
	if(BonkerBox_G.IsPlayingAs(player,BonkerBox_FWEnvi.GetSkinName())~=true)
		return
	end
	
	if(replayplayback==true)
		BonkerBox_C.ReplayDenyWarning(player)
		return
	end
	
	local countAsNum = tonumber(count)
	
	if(BonkerBox_G.IsNumber(countAsNum)~=true)
		return
	end
	
	if(BonkerBox_G.IsTable(player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()])~=true)
		player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()] = BonkerBox_FWFunc.GeneratePersistentTable()
	end
	
	player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()].bodycount = countAsNum
	BonkerBox_FWMain.ShutDown(player)
	BonkerBox_C.ReplayDelayWarning(player)
end)

local acc = BonkerBox_FWEnvi.GetAltColourCount()

for i=1,acc
	local valname = BonkerBox_FWEnvi.GetAltColourName(i)

	COM_AddCommand(BonkerBox_C.GenCommandName(BonkerBox_FWEnvi.GetSkinName(),valname),function(player,col)
		if(BonkerBox_G.IsPlayingAs(player,BonkerBox_FWEnvi.GetSkinName())~=true)
			return
		end
		
		if(replayplayback==true)
			BonkerBox_C.ReplayDenyWarning(player)
			return
		end
		
		local colstr = tostring(col)//because R_GetColorByName() is a C method, col being 'nil' is not the same as making 'nil' into a string which will still just be 'nil' not not "nil" written as a string. i loathe lua more every day! C is the one that has this right with a little thing called type safety.
		local foundcol = R_GetColorByName(colstr)//will always return SKINCOLOR_NONE aka 0 if no skin by the name was found
		
		if(foundcol==SKINCOLOR_NONE)
			BonkerBox_G.UserFacingWarning(player,"No skincolor by the name '"..colstr.."' exists. Defaulting to current player skincolor...")
		end
		
		if(BonkerBox_G.IsTable(player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()])~=true)
			player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()] = BonkerBox_FWFunc.GeneratePersistentTable()
		end
		
		player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()][valname] = foundcol
		BonkerBox_C.ReplayDelayWarning(player)
	end)
end

COM_AddCommand(BonkerBox_C.GenCommandName(BonkerBox_FWEnvi.GetSkinName(),"bodycolspeed"),function(player,speed)
	if(BonkerBox_G.IsPlayingAs(player,BonkerBox_FWEnvi.GetSkinName())~=true)
		return
	end
	
	if(replayplayback==true)
		BonkerBox_C.ReplayDenyWarning(player)
		return
	end
	
	local speednum = tonumber(speed)
	
	if(BonkerBox_G.IsNumber(speednum)~=true)
		return
	end
	
	if(BonkerBox_G.IsTable(player[BonkerBox_FWEnvi.GetSkinName()])~=true)
		player[BonkerBox_FWEnvi.GetSkinName()]={}
	end
	
	if(BonkerBox_G.IsTable(player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()])~=true)
		player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()] = BonkerBox_FWFunc.GeneratePersistentTable()
	end
	
	player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()].bodycolreversespeed = speednum <0
	player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()].bodycolspeed = speednum
	player[BonkerBox_FWEnvi.GetSkinName()].modcolourtimer = 0
	player[BonkerBox_FWEnvi.GetSkinName()].modcolouroffset = 0
	BonkerBox_C.ReplayDelayWarning(player)
end)

COM_AddCommand(BonkerBox_C.GenCommandName(BonkerBox_FWEnvi.GetSkinName(),"bodycolmapping"), function(player,mode)
	if(BonkerBox_G.IsPlayingAs(player,BonkerBox_FWEnvi.GetSkinName())~=true)
		return
	end
	
	if(replayplayback==true)
		BonkerBox_C.ReplayDenyWarning(player)
		return
	end
	
	//unlike the implementation of the 'bodycol' commands, i don't need to tostring() if nil gets passed into GetMappingModeEnumByName() because we're dealing with non-type-safe lua variables exclusively
	local asInteger = BonkerBox_FWEnvi.GetMappingModeEnumByName(mode,true)
	
	if(BonkerBox_G.IsNumber(asInteger)~=true)
		//still need to pissing change it into a string to print it though, drive me fucking bananas
		BonkerBox_G.UserFacingError(player,"The mapping mode '"..tostring(mode).."' doesn't exist.")
		return
	end
	
	if(BonkerBox_G.IsTable(player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()])~=true)
		player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()] = BonkerBox_FWFunc.GeneratePersistentTable()
	end
	
	player[BonkerBox_FWEnvi.GetSkinName()..BonkerBox_FWEnvi.GetPersistentCacheTableSuffix()].bodycolmapping = asInteger
	BonkerBox_C.ReplayDelayWarning(player)
end)

local bbfwc = {}
bbfwc.GhostBody = function() return cvar_ghostbody.value end
bbfwc.BodyCap = function() return cvar_bodycap.value end

rawset(_G,"BonkerBox_FWCons",bbfwc)