Looking for another coder to work with on Inner Animal [%]

Hello everyone. I’m needing a second coder to work with on Inner Animal, my second coder MyCheeze is rather extremely busy with school and will be unable to do much (or any at all) work on Inner Animal during the next year due to it being her final year of high school. Because of this I’m needing to find a replacement coder ASAP. With that being said, I’ll answer some question and explain what I’m looking for.

#1.) What is “Inner Animal”?
Inner Animal is an anthropomorphic game that is heavily inspired by the Hotline Miami series and is a mode-round based game, every round a different gamemode is randomly chosen to be played. Every gamemode is different then the rest, but all have the same gameplay more or less just with different objectives.Some of the gamemodes are completely free for all, others are team based or are both FFA and team based. Gamemodes vary from CTF, Deathmatch, KotH, Team Juggernaut vs everyone else, wave survival and elimination to name a few.
Gameplay at its very core is you running around shooting, slicing, knocking around and jumping on everyone else to win, however it sounds boring and simple right? Its not so simple, in just a single hit your life could be over, most weapons in Inner Animal are one hit kills, with the exception that some characters require multiple hits to kill. But thats not everything either, every map has a limited number of weapons that will spawn, melee weapons have an infinite number of uses and never break, while ranged weapons only have a single magazine and cannot pick up ammo or reload. Even though a gun in your hand stops spitting lead and only clicks when you pull the trigger, it is not useless. You can throw everything you can pick up at your enemies to knock them down or kill them. There are plenty of world objects around you to use as a makeshift weapon if you simply look around, just be warned that if you throw a something at someone and miss, they might pick up that object and use it on you.

tl:dr: A modernized, updated and overall much better version of this with bloody fluff everywhere. (Requires 2 or more players) / the roblox multiplayer version of this and this.


#2.) How is Inner Animal going to be monetized?

(Just about) Everything in Inner Animal is obtainable for freeif a player plays long enough, characters are unlocked by playing the game long enough to get the necessary amount of experience points to unlock, or can be bought with premium currency (which has no official name so I’ll refer to it as “Gold”) . Gold is used to purchase new characters (which is the much faster way of obtaining them rather then playing the game till you have the required amount of points) and consumables. Consumables in the game are essentially stat boosters and have 3 types of consumability:

1.) Time-based consumables
Time-based consumables only get consumed as you play the game, meaning that for every second you are playing during a round, the consumable is being used. These consumables do not stack but rather have their time extended whenever purchased or awarded.

2.) Per-life consumables
These are consumed once per life.

3.) Per-round consumables
These are only consumed once the round has ended.

Consumables have different effects, some are EXP boosts, armor, increased movement speed, lethal punches/throws, extra ammo, etc. And to make it fair for all players, consumables are not strictly pay-to-obtain. You are awarded a random consumable for winning, being the MVP, most kills, best accuracy, and just playing the game in general. Gold is also awarded to players who login daily, win a lot and complete daily challenges and rank up. (To keep it from being a complete P2W). With all of that being said, the only thing that will be sold is the premium currency. And in the future after release, character packs will also be available for purchase.


3.) What am I looking for?

I’m looking for an advanced coder who is able to get things done by a reasonable deadline, has knowledge and experience with writing their own 2D physics in a 3D world (This includes collisions solving, pushing objects around and custom hinges) and is able to read, to understand and to work with my coding, as well as being able to write clean, efficient and readable code and as well as comment their own code.

An example of my coding... [code] local Server = nil local Client = nil

return function(ForcedRunMode) – Fury is a function, it’s to keep client and server code different while in PlaySolo.
if Client ~= nil and ForcedRunMode == “Client” then – (game:GetService(“RunService”):IsClient() and game.Players.LocalPlayer ~= nil) then
Client:PrintVersion()
Client:PrintRunMode()
return Client
elseif Server ~= nil and ForcedRunMode == “Server” then – (game:GetService(“RunService”):IsServer() or game.Players.LocalPlayer == nil) then
Server:PrintVersion()
Server:PrintRunMode()
return Server
end

– ROBLOX Services –

local RunService = game:GetService(“RunService”)
local RS = game:GetService(“ReplicatedStorage”)
local Players = game:GetService(“Players”)
local RbxUtility = LoadLibrary(“RbxUtility”)

– Glboal Variables –

local Root = script
local CustomServicesFolder = Root:WaitForChild(“Custom Services”)
local CustomObjectsFolder = Root:WaitForChild(“CustomObjects”)
local ModulesFolder = Root:WaitForChild(“Modules”)
local RemotesFolder = Root:WaitForChild(“Remotes”)

local FuryReplicationRequest – Is set later
local FuryReplicationUpdate – Is set later
local InitialPing – Is set later
local PingRemote – Is set later

– Engine Variables –

local EngineName = Root.Name
local Engine = {}

Engine.FilePaths = {}

– Engine Configuration –

Engine.Configuration = {
EngineName = EngineName,
Version = “v2”,
PrintHeader = EngineName…": “,
WarnHeader = EngineName…” Warning: “,
ErrorHeader = EngineName…” Error: ",
}

Engine.RunMode = nil – Is set under Engine Logic

function Engine:PrintVersion()
warn(Engine.Configuration.PrintHeader…" “…Engine.Configuration.Version…” is up and running!")
end

function Engine:GetRunMode()
local RunMode
if RunService:IsClient() and game.Players.LocalPlayer ~= nil then
RunMode = “Client”
if Client == nil then
Client = Engine
end
elseif RunService:IsServer() or game.Players.LocalPlayer == nil then
RunMode = “Server”
if Server == nil then
Server = Engine
end
end
return RunMode
end

function Engine:PrintRunMode()
print(Engine.Configuration.PrintHeader…" "…Engine.RunMode)
end

@Name: Engine Create
@Description: Mimics the RbxUtility:Create()
@Parameters:
– ClassName: The ClassName of the object you wish to create.
– Properties:

function Engine:Create(ClassName, Properties)
local Object = Instance.new(ClassName)
if Properties then
local Parent
for Property, Value in pairs(Properties) do
if Property == “Parent” then
Parent = Value
else
Object[Property] = Value
end
end
Object.Parent = Parent
end
return Object
end

@Name: Engine Pools
@Description: A Pool is a table where all scripts on the local machine will have access to add or remove pools and edit pool data. –
@Parameters:
– PoolName: The name of the pool.
– IsDynamic: If true, the pool will have the ablity to be listened to by scripts via .Updated event.
– PoolData: Any sort of data that needs to be added to the pool upon creation.

Engine.Pools = {}

function Engine:CreatePool(PoolName, PoolData, IsDynamic)
if IsDynamic then
local Pool = {}
Pool.Data = {}
Pool.Updated = RbxUtility:CreateSignal()

	for i,v in pairs(PoolData) do
		Pool.Data[i] = v
	end
		
	
	Pool.__index = (function(self, Index)
		return Pool[Index] or self.Data[Index]
	end)
	
	Pool.__newindex = (function(self, Index, Value)
		self.Data[Index] = Value
		self.Updated:fire(Index, Value)
	end)	
	
	Engine.Pools[PoolName] = setmetatable({}, Pool)	
else
	Engine.Pools[PoolName] = PoolData or {}
end
return Engine.Pools[PoolName]

end

function Engine:GetPool(PoolName)
if Engine.Pools[PoolName] == nil then
Engine.Pools[PoolName] = {}
end
return Engine.Pools[PoolName]
end

function Engine:DeletePool(PoolName)
Engine.Pools[PoolName] = nil
end

@Name: Custom objects
@Description: Allows for you to load user created objects.

function Engine:LoadCustomObject(PATH, NAME)
if string.sub(PATH, #PATH) ~= “/” then
PATH = PATH…"/"
end
return Engine.FilePaths[PATH][NAME]
end
–[[
do

local function Recursive(Folder, FilePath)
	if FilePath == nil then
		FilePath = "Objects/"
	end
	for i,v in pairs(Folder:GetChildren()) do
		local NewFilePath = FilePath..v.Name.."/"
		local FolderData = {
			Parent = Folder.Parent,
			Folder = Folder,
		}
		if v:IsA("ModuleScript") then
			FolderData[v.Name] = require(v)
		elseif v:IsA("Folder") then
			Recursive(v, NewFilePath)
		end
		Engine.FilePaths[NewFilePath] = FolderData
	end
end
Recursive(CustomObjectsFolder)

for i,v in pairs(Engine.FilePaths) do
	print(i,v)
end

end
–]]

– Engine Modules –

Engine.Modules = {}

function Engine:GetModule(ModuleName)
if Engine.Modules[ModuleName] ~= nil then
return Engine.Modules[ModuleName]
else
local found = ModulesFolder:FindFirstChild(ModuleName, true)
if found then
if found:IsA(“ModuleScript”) then
local m = require(found)
Engine.Modules[ModuleName] = m
print(Engine.Configuration.PrintHeader…“successfully loaded “…ModuleName…”.”)
return m
else
error(Engine.Configuration.ErrorHeader…“Module '”…tostring(ModuleName)…"’ is not a ModuleScript!")
end
else
error(Engine.Configuration.ErrorHeader…“Module '”…tostring(ModuleName)…"’ wasn’t found!")
end
end
end


– Engine Services –

Engine.Services = {}

@name: GetService
@Description: Returns the requested service.

function Engine:GetService(ServiceName) – this function mimics game:GetService() except it allows for custom services.
if Engine.Services[ServiceName] ~= nil then
return Engine.Services[ServiceName]
else
local CustomService = CustomServicesFolder:FindFirstChild(ServiceName, true)
if CustomService ~= nil then
Engine.Services[ServiceName] = require(CustomService)(Engine) – Custom services need to have access to Fury.
return Engine.Services[ServiceName]
elseif CustomService == nil then
Engine.Services[ServiceName] = game:GetService(ServiceName)
return Engine.Services[ServiceName]
end
end
end

– Engine Remotes –


@Name: GetRemote
@Description: Yields code until the specified Remote is found at the path.
@Parameters:
– PATH: Where the specified remote will be.
– NAME: The specific name of the remote you are looking for.

function Engine:GetRemote(PATH, NAME)
if string.sub(PATH, #PATH) ~= “/” then
PATH = PATH…"/"
end
if Engine.FilePaths[PATH] ~= nil then
return Engine.FilePaths[PATH][NAME]
else
warn(“Yielding Fury:GetRemote(”…PATH…", “…NAME…”) until Engine.FilePaths["…PATH…"] is found.")
while Engine.FilePaths[PATH] == nil do
RunService.Heartbeat:wait()
end
warn(“Engine.FilePaths[”…PATH…"] is found. Yielding Fury:GetRemote("…PATH…", “…NAME…”) until Engine.FilePaths["…PATH…"]["…NAME…"] is found.")
while Engine.FilePaths[PATH][NAME] == nil do
RunService.Heartbeat:wait()
end
return Engine.FilePaths[PATH][NAME]
end
end

@Name: CreateRemote
@Description: Creates the specified remote object that the CLASSTYPE parameter specifies.
@Parementers:
– PATH: Where the remote will be instanced and saved to.
– NAME: The name and Index of the remote.
– CLASSTYPE: Specifies which object will be instanced, you can currently use: RemoteEvent, RemoteFunction, BindableEvent, BindableFunction, ScriptSignal
– DO_NOT_REPLICATE_TO_CLIENTS: By default this is set to false and should only be set to true for hidden remotes.
@Notes: ScriptSignal is never replicated to the clients.

function Engine:CreateRemote(PATH, NAME, CLASSTYPE, DO_NOT_REPLICATE_TO_CLIENTS)
local FolderData
if Engine.FilePaths[PATH] ~= nil then – Check to see if this file path is alreay cached or not.
FolderData = Engine.FilePaths[PATH]
else – Create the new path
local CurrentFolder = Root
local FoldersToSeachFor = {}

	local CurrentPath = ""
	for NextFolder in string.gmatch(PATH, "[^/]+") do
		if CurrentFolder:FindFirstChild(NextFolder) then
			CurrentFolder = CurrentFolder[NextFolder]
		else
			local NewFolder = Instance.new("Folder")
			NewFolder.Name = NextFolder
			NewFolder.Parent = CurrentFolder
			CurrentFolder = NewFolder
		end
		
		CurrentPath = CurrentPath..NextFolder.."/"
		if Engine.FilePaths[CurrentPath] == nil then
			Engine.FilePaths[CurrentPath] = {
				Name = NextFolder,
				Parent = CurrentFolder.Parent,
				Folder = CurrentFolder,
			}
		end
	end
	FolderData = Engine.FilePaths[CurrentPath]
end

local InstancedRemote
if FolderData[string.reverse(NAME)] ~= nil and FolderData[string.reverse(NAME)]:IsA("BindableEvent") then --FolderData.Folder:FindFirstChild(string.reverse(NAME)) ~= nil and FolderData.Folder[string.reverse(NAME)]:IsA("BindableEvent") then
	InstancedRemote = RbxUtility:CreateSignal()
	FolderData[NAME] = InstancedRemote
elseif FolderData[NAME] ~= nil then
	InstancedRemote = FolderData[NAME]
	FolderData[NAME] = InstancedRemote
else
	if CLASSTYPE == "ScriptSignal" then
		InstancedRemote = RbxUtility:CreateSignal()
		local BindableEvent = Instance.new("BindableEvent") -- This BindableEvent is only here to screw with explioters.
		BindableEvent.Name = string.reverse(NAME)
		BindableEvent.Parent = FolderData.Folder
	elseif CLASSTYPE == "BindableEvent" then
		InstancedRemote = Instance.new("BindableEvent")
		InstancedRemote.Name = NAME
		InstancedRemote.Parent = FolderData.Folder
	elseif CLASSTYPE == "BindableFunction" then
		InstancedRemote = Instance.new("BindableFunction")
		InstancedRemote.Name = NAME
		InstancedRemote.Parent = FolderData.Folder
	elseif CLASSTYPE == "RemoteEvent" then
		InstancedRemote = Instance.new("RemoteEvent")
		InstancedRemote.Name = NAME
		InstancedRemote.Parent = FolderData.Folder
	elseif CLASSTYPE == "RemoteFunction" then
		InstancedRemote = Instance.new("RemoteFunction")
		InstancedRemote.Name = NAME
		InstancedRemote.Parent = FolderData.Folder
	end
	FolderData[NAME] = InstancedRemote

	if Engine.RunMode == "Server" and not DO_NOT_REPLICATE_TO_CLIENTS and CLASSTYPE ~= "ScriptSignal" then
		-- TO-DO: Replicate to clients
		FuryReplicationUpdate:FireAllClients(
			"RemoteCreated", {PATH, NAME, CLASSTYPE}
		)
	end
end
return InstancedRemote

end

function Engine:GetMouse()
–if Engine.RunMode == “Client” then
if Engine.Mouse == nil then
Engine.Mouse = require(script:WaitForChild(“Mouse”))
end
return Engine.Mouse
–else
– error(“Only clients can request the mouse.”)
–end
end

function Engine:RenderPartBetweenPoints(A,B, KeepTime)
local beam = Instance.new(“Part”, workspace:FindFirstChild(“RayIgnore”) or nil)
beam.BrickColor = BrickColor.new(“Bright red”)
beam.Material = “Neon”
beam.Transparency = 0.25
beam.Anchored = true
beam.Locked = true
beam.CanCollide = false

local distance = (A - B).magnitude
beam.Size = Vector3.new(0.2, 0.2, distance)
beam.CFrame = CFrame.new(A, B) * CFrame.new(0, 0, -distance / 2)

delay(KeepTime or 1,function() beam:Destroy() end)

end

function Engine:Raycast(Position, Direction, IgnoreList, Visualize, RenderTime, terrainCellsAreCubes, ignoreWater)
if IgnoreList == nil then
IgnoreList = {}
end
local Part, Point, Surface = game.Workspace:FindPartOnRay(Ray.new(Position, Direction), terrainCellsAreCubes or false, ignoreWater or false)

if Visualize then
	Engine:RenderPartBetweenPoints(Position, Point, RenderTime)
end	

return Part, Point, Surface

end

function Engine:RaycastWithIgnoreList(Position, Direction, IgnoreList, Visualize, RenderTime, terrainCellsAreCubes, ignoreWater)
if IgnoreList == nil then
IgnoreList = {}
end
local Part, Point, Surface = game.Workspace:FindPartOnRayWithIgnoreList(Ray.new(Position, Direction),IgnoreList, terrainCellsAreCubes or false, ignoreWater or false)

if Visualize then
	Engine:RenderPartBetweenPoints(Position, Point, RenderTime)
end	

return Part, Point, Surface

end

function Engine:RaycastWithWhitelist(Position, Direction, IgnoreList, Visualize, RenderTime, terrainCellsAreCubes, ignoreWater)
if IgnoreList == nil then
IgnoreList = {}
end
local Part, Point, Surface = game.Workspace:FindPartOnRayWithWhitelist(Ray.new(Position, Direction),IgnoreList, terrainCellsAreCubes or false, ignoreWater or false)

if Visualize then
	Engine:RenderPartBetweenPoints(Position, Point, RenderTime)
end	

return Part, Point, Surface

end

– Engine Logic –

local function PopulateFilePaths(RootFolderObject, RootFolderName)

local function Recursive(FolderObject, FilePath, Folder)
	if FolderObject:IsA("Folder") then
		if Folder == nil then
			Folder = {}
		end
		
		for FolderIndex, FolderContient in pairs(FolderObject:GetChildren()) do
			if FolderObject:IsA("Folder") then 
				local NewFilePath = FilePath..FolderContient.Name.."/"
				Folder[FolderContient.Name] = Recursive(FolderContient, NewFilePath, Folder)
			else
				Folder[FolderContient.Name] = FolderContient
			end
		end
		
		Engine.FilePaths[FilePath] = Folder
		return Folder
	else
		return FolderObject
	end
end

Recursive(RootFolderObject, RootFolderName.."/")

end

do
PopulateFilePaths(CustomServicesFolder, “Services”)
PopulateFilePaths(CustomObjectsFolder, “Objects”)
PopulateFilePaths(ModulesFolder, “Modules”)
PopulateFilePaths(RemotesFolder, “Remotes”)

for i,v in pairs(Engine.FilePaths) do
	print(i,v)
end

end

Engine.RunMode = Engine:GetRunMode()

if Engine.RunMode == “Server” then
FuryReplicationRequest = Instance.new(“RemoteFunction”)
FuryReplicationRequest.Name = “FuryReplicationRequest”
FuryReplicationRequest.Parent = Root

FuryReplicationUpdate = Instance.new("RemoteEvent")
FuryReplicationUpdate.Name = "FuryReplicationUpdate"
FuryReplicationUpdate.Parent = Root

InitialPing = Instance.new("RemoteFunction")
InitialPing.Name = "InitialPing"
InitialPing.Parent = Root

InitialPing.OnServerInvoke = function()
	return tick()
end

PingRemote = Instance.new("RemoteFunction")	
PingRemote.Name = "PingRemote"
PingRemote.Parent = Root

PingRemote.OnServerInvoke = function()
	return tick()
end

Server = Engine

else
FuryReplicationRequest = Root:WaitForChild(“FuryReplicationRequest”, 100)
FuryReplicationUpdate = Root:WaitForChild(“FuryReplicationUpdate”, 100)
InitialPing = Root:WaitForChild(“InitialPing”, 100)
PingRemote = Root:WaitForChild(“PingRemote”, 100)

FuryReplicationUpdate.OnClientEvent:connect(function(ReplicationType, Data)
	warn("ReplicationType =", ReplicationType, "= {")
	for i,v in pairs(Data) do
		print("	"..i,"=",v)
	end
	print("}")
	if ReplicationType == "UpdateFilePaths" then
		Engine.FilePaths = Data
	elseif ReplicationType == "RemoteCreated" then
		warn(ReplicationType)
		Engine:CreateRemote(Data[1], Data[2], Data[3])
	end
end)

coroutine.resume(coroutine.create(function()
	Engine.Ping = 0
	local function PingPong()
		-- TO-DO: keep this from breaking
		LastServerTick2 = LastServerTick1
		local s = tick()
		LastServerTick1 = PingRemote:InvokeServer(LastServerTick1)
		Engine.ServerTick = LastServerTick1
		wait(0.2) -- Remotes operate on 1/20th second heartrate.
		Engine.Ping = (tick() - s) - 0.2
		PingPong()
	end

	local t = InitialPing:InvokeServer()
	LastServerTick2 = LastServerTick1
	LastServerTick1 = t
	Engine.ServerTick = LastServerTick1
	PingPong()
end))	

local OnRenderSteppedFunctions = {}

function Engine:AddFunctionToRenderStep(func)
	OnRenderSteppedFunctions[#OnRenderSteppedFunctions+1] = func
end	

RunService.RenderStepped:connect(function(TimeSinceLastFrame)
	Engine.ServerTick = Engine.ServerTick + TimeSinceLastFrame
	for i = 1, #OnRenderSteppedFunctions do
		OnRenderSteppedFunctions[i](TimeSinceLastFrame)
	end
end)

Engine.LocalPlayer = Engine:GetService("Players").LocalPlayer

Client = Engine

end
– print("["…Engine.RunMode…"] FuryReplicationUpdate =",FuryReplicationUpdate)

Engine:PrintVersion()
Engine:PrintRunMode()

return Engine




end
[/code]

For an example of what I am looking for is a much better version of my and MyCheeze’s physics solver that you can see here: Inner Animal Redux - Roblox that can properly handle moving objects and not teleport through walls (you will see that if you jump a few frames while hitting a corner) and be able to create a physics solver that both server and client can use to move characters. By that I mean for the client to use the solver to move its own local character, push open doors, etc and for the server to be able to use it do the same with its own characters (NPCs). You will also be handling the physics and replication of thrown weapons/objects as they spin around in the air while thrown and need to react somewhat believable when they hit an object by “bouncing” off the object.


#4.) I’m interested. How and when do I get monies?

I’m very much aware that money is of a big thing when it comes to hiring developers… And to be 100% honest with you I only have a total of 740 robucks in combined total from GuestCapone and GuestCorleone as shown below:



and with only another month of BC left, I’m only going to make another 789 more robucks from the daily login bonus (if I log in every single day) on GuestCapone… which is a lovely total of 1,529 robucks. Not a whole lot I know, which is why I’m not even going to bother offering R$ upfront because I don’t even have enough to make a newbie jump in joy. What about USD you might be wondering? To also be honest, I only have 54 dollars in cash, mostly in quarters and 0 in my bank account, I had around 750 USD earlier this year but I had to pay the rent for a month due to some medical bills draining my parents account. I also can’t give any of that money because when the game is done I’ll be spending every penny I have (literally) on advertisement for Inner Animal. And before anyone suggests getting a job, I have an unpaying job with my father, one I would love to dump for a paying one but cant because its literally paying the rent and thats it, and if I don’t help him, we literally don’t have a home anymore… With all of that being said, the short answer is you get paid when the game is released, after that it will be every 30 days with 10-40% of all earnings made depending on how much you’re willing to do the work, and how you work with me.

If percentage isn’t enough, only thing left to offer is giving you my best effort at untextured (I’m not that good at texturing) 3D models if you have reference images… I know its not a lot but it is all I can offer. If you’re interested you can send me a PM here on the devforums, and if you know someone who is interested but are not on the devforums, here is a tweet that explains what I am needing and have them send me a direct message on Twitter @guestcapone if they are interested. I look forward to hearing from someone and will answer any questions that you have.

I’m quite interested but It’d probably want 50% of all earnings and for the project to be a group place. I’m able to do what as you described too.

Do you have an example place?

Pretty sure that’s something that was posted while he was compromised

He’s compromised?

EDIT: derp. read lounge.

2 Likes

Yeah, not me, sorry about that.

Job position filled by Masteralan.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.