Full Open Sourced Code Excluding Phrase Module Libraries located in the model linked above
--Designed to created textual observations of labeled surroundings and return a table of observations.
--Can Be used to inform an LLM agent of its surroundings in a video game
--Declare global variables for all observed variables.
local closestPlant, numPlants, plantsize, plantdist --= aware.near.plant(root, 40)
local closestTree, numTrees, treesize, treedist --= aware.near.tree(root, 80)
local closestStructure, numStructures, structuresize, strucdist
local closestEnemy, numEnemies, enemysize, enemydist
local closestNPC, numNPCs, npcsize, npcdist,npcarray
local closestPlayer, numPlayers, plrsize, plrdist
local closestRubble, numRubble, rubblesize, rubbledist
local closestChest, numChests, chestsize, chestdist
local closestGroundItem, numGroundItems, itemsize, itemdist
local closestHouse, numHouses, housesize, housedist
local closestDungeon, numDungeons, dungsize, dungdist,Dungeonarray
local closestFish, numFish, Fishsize, Fishdist
local closestFurn, numFurn, Furnsize, Furndist,Furnarray
local closestBoid, numBoid, boidsize, boiddist,boidarr
local plantarr,treearr,strucarr,npcarr,enemyarr,plrarr,chestarr,itemarr,fisharr,rubbarr
--Time used to limit updating of tables
local optime=os.time()
local terrain=workspace.Terrain
local phraselib=require(script.PhraseLibrary)
local DescriptionModule = require(script.JudgementLibrary)
--Load All of these as local variables for the judgement library
local phrases = DescriptionModule.phrases
local judgeheightmatrixSizes = DescriptionModule.judgeHeightMatrix.sizes
local judgehmatrixStrings = DescriptionModule.judgeHeightMatrix.strings
local judgewidthmatrixSizes = DescriptionModule.judgeWidthMatrix.sizes
local judgewidthmatrixStrings = DescriptionModule.judgeWidthMatrix.strings
local judgethicknessmatrixSizes = DescriptionModule.judgeThicknessMatrix.sizes
local judgethicknessmatrixStrings = DescriptionModule.judgeThicknessMatrix.strings
local jmatrixSizes = DescriptionModule.judgeSizeMatrix.sizes
local judgehsizematrixStrings = DescriptionModule.judgeSizeMatrix.strings
local judgeamntdistributio = DescriptionModule.judgeAmountDistribution.sizes
local judgeamntstrings = DescriptionModule.judgeAmountDistribution.strings
local toomany = DescriptionModule.tooMany
local emotiondesc = DescriptionModule.emotionDesc -- Assuming this is an empty table as per your original variable
local judgematrixSizes = DescriptionModule.judgeMatrix.sizes
local judgematrixStrings = DescriptionModule.judgeMatrix.strings
local rockjudgematrixSizes = DescriptionModule.rockJudgeMatrix.sizes
local rockpiece = DescriptionModule.rockJudgeMatrix.pieces
local heightmatrixSizes = DescriptionModule.heightMatrix.sizes
local heightmatrixstrings = DescriptionModule.heightMatrix.strings
local heightmatrixSizes = {-1, -0.67, -0.33, 0, 0.33, 0.67, 1} -- This seems to be a duplicate, ensure to use the correct one from the module if needed
local judgepowerSizes = DescriptionModule.judgePowerMatrix.sizes
local judgepowerStrings = DescriptionModule.judgePowerMatrix.strings
local furthersubject=DescriptionModule.Furthersubject
--Used For String Matching considering Filter words.
local RunService = game:GetService("RunService")
local isLocal = RunService:IsClient()
if isLocal and game.Players.LocalPlayer.PlayerGui:FindFirstChild("Chatbot") then
processor=game.Players.LocalPlayer.PlayerGui.Chatbot.LocalProcessor
elseif game.ReplicatedStorage:FindFirstChild("GlobalSpells") then
processor=game.ReplicatedStorage.GlobalSpells.BindableFunction
end
local aware = {}
aware["get"]={}
aware["judge"]={}
aware["near"]={}
aware.judge.human={}
local previousroot=nil
local objecttable
local range = 80
-- Define the raycast parameters
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Include
params.FilterDescendantsInstances = {workspace.Terrain}
params.IgnoreWater = false
local waterdirections = {
Vector3.new(0, -5, range), -- forward
Vector3.new(0, -5, -range), -- backward
Vector3.new(range, -5, 0), -- right
Vector3.new(-range, -5, 0), -- left
Vector3.new(0, range, 0), -- up
Vector3.new(0, -range, 0) -- down
}
-- Rewriting the variables using the DescriptionModule
local globalrng=Random.new(os.time())
local newtable = {"MapObjects",--structures
"Crystals",--crystals
"Plants",
"Enemys",
"Rubble",
"Trees",
"Chests",
"GroundItems",--loots
"Houses",--house type
"AmbientAreas",--Zoned Areas
"NPCS",
"Furniture",
"Fish",
"Boids"
}
for i,v in newtable do --generate directories if their is none
if workspace:FindFirstChild(v)==nil then
local f=Instance.new("Folder")
f.Name=v
f.Parent=workspace
end
end
local tablekeys = {["mapobject"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.MapObjects},
["crystal"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Crystals},
["plants"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Plants},
["enemys"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Enemys},
["rubble"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Rubble},
["trees"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Trees},
["chests"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Chests},
["grounditems"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1},workspace.GroundItems},
["houses"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Houses},
["players"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, game.Players},
["dungeons"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1},workspace.AmbientAreas},
["npcs"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.NPCS},
["furniture"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Furniture},
["fish"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Fish},
["boid"] = {{["datatable"] = nil, ["writetime"] = optime, ["refreshrate"] = 1}, workspace.Boids},
}
local awarekeys = {["observations"] = {["datatable"] = nil, ["writetime"] = -60, ["refreshrate"] = 60}
}
local matsolutions={["LeafyGrass"]="leafy grass",
["WoodPlanks"]="wooden planks",
["CrackedLava"]="cracked lava",
["ground"]="dirt"
}
local grid = Vector3.new(10, 20, 10) -- grid size
-- grid members
local function query(query,key)
if processor then
return processor:Invoke("SingleQuery",{query,key,nil,nil,true})
else
return string.gmatch(query,key)()
end
end
local function has_punctuation(text)
-- Define a pattern that matches any punctuation character
local punctuation = "[.,;:!?]"
-- Get the length of the text
local length = string.len(text)
-- Get the last character of the text
local last = string.sub(text, length, length)
-- Get the second last character of the text
local second_last = string.sub(text, length - 1, length - 1)
-- Check if the last character is a punctuation
if string.match(last, punctuation) then
-- Check if the second last character is a punctuation and the last character is a space
-- Return true
return true
elseif string.match(second_last, punctuation) and last == " " then
-- Return true
return true
else
-- Return false
return false
end
end
local function observearray(root,pos,numFurn,closestFurn,Furnarray,a)
local FurnitureText=""
if a==nil then
a=""
end
if Furnarray~=nil and #Furnarray>0 then
if numFurn >= 1 and closestFurn and Furnarray then
local iterations=0
local groups={}--group duplicate names to generalize multiple objects
local groupiter=0
for i,closeFurniture in Furnarray do
--group by distance,direction and name.
local dist, dir = aware.judge.distance(root,closeFurniture.distance, pos, aware.get.root2(closeFurniture.maininstance).Position, 80)
local id =aware.judge.object(closeFurniture.maininstance)
if groups[dir..id]==nil then--initalize the subtable
groupiter+=1
groups[dir..id]={dist,dir,id,[4]=1}
else
groups[dir..id][4]+=1--increment the value
end
end
local idhash={}--hash table of ids
local maxiterations=math.min(groupiter,3)-- only observe 3 objects name groups
local amntjudged=0
table.sort(groups,function(a,b) return a[4]>b[4] end)
for i,closeFurniture in groups do
iterations+=1
--grammar rules
if iterations==maxiterations-1 then FurnitureText=FurnitureText.." and "
elseif iterations>=2 and iterations~=maxiterations then FurnitureText=FurnitureText..", " end
--unpack the distance and direction.
local dist,dir=closeFurniture[1],closeFurniture[2]
--judge the amount of objects.
local id=closeFurniture[3]
--local totalamnt=idgroups[id][1]
amntjudged+=closeFurniture[4]
local amnt=a if closeFurniture[4]>1 then amnt=aware.judge.amnt(closeFurniture[4]).." " end
if closeFurniture[4]>1 then
id=id.."s"
end
FurnitureText = FurnitureText..amnt..id .. " " .. dist .. "" .. dir
if iterations==maxiterations then break end
end
local maxiterations=amntjudged-- only observe 3 objects name groups
if #Furnarray-maxiterations>=2 then--later code will generalize the rest if conditions not met.
FurnitureText..=", "
else
FurnitureText..=". "
end
return FurnitureText,maxiterations
end
end
return "",0
end
local function modify_string(input_string)
local modified_words = {}
for word in input_string:gmatch("[A-Z][^A-Z]*") do
local modified_word = word:gsub("^%l", string.upper)
table.insert(modified_words, modified_word)
end
-- Replace multiple spaces with a single space
local modified_string = table.concat(modified_words, " "):gsub("%s+", " ")
return modified_string
end
local function tablehandler(location)
return location:GetChildren()
end
local function gettime()
return os.time()
end
local function getinvent(npc,plr)
local invent =npc:FindFirstChild("Inventory")--npc inventory
if invent==nil then--check if a party member
print("Attempting to get party member")
--local plr=npc:FindFirstChild("Owner2")
if plr==nil then
plr=game.Players:GetPlayerFromCharacter(npc)
end
if plr then
local partym=plr.Levels.PartyS1.Value
if partym==npc.Name or npc.Humanoid.DisplayName==partym then
print("Found party member")
local partydata=nil
local index=nil
for i=1, 9 do
if plr.Inventory["CustomCharacter"..i].Value==partym then --if the party member is found get data index
index=i
break
end
end
invent = {
Armor = plr.Levels.PartyS1Armor,
Amulet = plr.Levels.PartyS1Amulet,
Boots = plr.Levels.PartyS1Boots,
Book = plr.Levels.PartyS1Book,
CustomCharacter = plr.Inventory["CustomCharacter" .. index],--Custom character name
TopClothes = plr.Inventory["TopClothes" .. index],--custom clothes
PantSkirtDress = plr.Inventory["PantSkirtDress" .. index],
Cape = plr.Levels.PartyS1Cape,
Helmet = plr.Levels.PartyS1Halo,
Shield = plr.Levels.PartyS1Shield,
Sword = plr.Levels.PartyS1Weapon,
--Gun = plr.Levels.PartyS1Gun,
Wand = plr.Levels.PartyS1Staff,
-- Bracelet = plr.Levels.PartyS1Bracelet
}
print("Created party meta data.")
print(invent)
return invent
end
end
end
return invent
end
function aware.ConstructEmotions(nam,get)
local emotiondesc=require(script.Other).ConstructEmotions(nam,get)
if get==true then
return emotiondesc[aware.mathrandom(1,#emotiondesc)]
end
return emotiondesc
end
function aware.Updatetable(a, b, c, d) --a=key b=arraylocation c=refreshrate d=array of b
local e, f
local b = b
local c = c
local d = d
if tablekeys[a] then
e, b = tablekeys[a][1], tablekeys[a][2]
c = e["refreshrate"]
f = e["datatable"]
end
tablekeys[a] = {{["datatable"] = tablehandler(b), ["writetime"] = os.time(), ["refreshrate"] = c}, b}
if d == nil then
return tablekeys[a][1]["datatable"]
end
end
function aware.uptable(a)
if tablekeys[a] then
local b, c = tablekeys[a][1], tablekeys[a][2]
local d = tonumber(b["writetime"])
local e = b["refreshrate"]
local f = b["datatable"]
tablekeys[a] = {{["datatable"] = tablehandler(c), ["writetime"] = os.time(), ["refreshrate"] = e}, c}
return tablekeys[a][1]["datatable"]
else
-- print("No table to return")
return nil
end
end
function aware.Gettable(a)
if tablekeys[a] then
local b, c = tablekeys[a][1], tablekeys[a][2]
local d = tonumber(b["writetime"])
local e = b["refreshrate"]
local f = b["datatable"]
if d + e < os.time() and f ~= nil then
return f
else
tablekeys[a] = {{["datatable"] = tablehandler(c), ["writetime"] = os.time(), ["refreshrate"] = e}, c}
return tablekeys[a][1]["datatable"]
end
else
-- print("No table to return")
return nil
end
end
function aware.mathrandom(min,max)
if min==nil then
----print("Min Integer is nil converted to 0")
min=0
end
if max==nil then
-- --print("Max Integer is nil converted to 1")
max=1
end
return globalrng:NextInteger(min, max)
end
function aware.cap(str)
-- Check if the input is a valid string
if type(str) ~= "string" then
return str
end
-- Get the first character and the rest of the string
local first = str:sub(1, 1)
local rest = str:sub(2)
-- Return the capitalized string
return first:upper() .. rest
end
function aware.randomizeStringLight(str,interphrases,randomize,once)
local newS = str
local s=str
for j, phrases in ipairs(interphrases) do
for k, phrase in ipairs(phrases) do
if s:lower():find(phrase) then
if phrase:lower():find(s:lower())==nil then
-- Pick a random phrase from the same group
local randomPhrase
if randomize==nil then
randomPhrase = phrases[aware.mathrandom(#phrases)]
else
randomPhrase= phrases[randomize]
end
newS = newS:gsub(phrase, randomPhrase)
if once==true then break end
end
end
end
end
return newS
end
function aware.get.CombatDescription(Char)
return require(script.Other).CombatDescription(Char)
end
function aware.get.QuestData(player)
if player.PlayerGui:FindFirstChild("Bars") then
local dataloc=player.PlayerGui.Bars.Quest
local qdata=player.Quest
local v="Item"
local datatable={}
for i=1, 27 do
local item=dataloc:FindFirstChild("Item"..i)
if item then
local questtext=dataloc["Item"..i].Description.Text
if questtext~="" and questtext:gmatch("%w+") then
local goal=qdata["Item"..i].Value
datatable[goal]=questtext
end
end
end
return datatable
end
return nil
end
function aware.get.root(instance, itself)
if instance ~= nil then
local selfrecog = nil
if instance:FindFirstChild("HumanoidPart") ~= nil then
return instance.HumanoidRootPart
elseif instance:IsA("folder") ~= nil then
return instance:FindFirstChildOfClass("Model").PrimaryPart
elseif instance:IsA("BasePart") then
return instance
elseif instance:IsA("Model") then
if instance.PrimaryPart then
return instance.PrimaryPart
else
return instance:FindFirstChildOfClass("BasePart")
end
end
end
end
function aware.get.root2(instance)
if instance ~= nil then
if instance:IsA("BasePart") then
return instance
elseif instance.Parent==workspace.AmbientAreas then
return instance:FindFirstChild("Part")
elseif instance:FindFirstChild("HumanoidRootPart") ~= nil then
return instance.HumanoidRootPart
elseif instance.Parent==workspace.Fish then
return instance.PrimaryPart
elseif instance:IsA("Folder") then
if instance:FindFirstChildOfClass("BasePart")==nil then
if instance:FindFirstChildOfClass("Model") then
if instance:FindFirstChildOfClass("Model").PrimaryPart~=nil then
return instance:FindFirstChildOfClass("Model").PrimaryPart
elseif instance:FindFirstChildOfClass("Model") :FindFirstChildOfClass("BasePart") then
return instance:FindFirstChildOfClass("Model") :FindFirstChildOfClass("BasePart")
end
return instance:FindFirstChildOfClass("Model"):FindFirstChild("Handle")
end
else return instance:FindFirstChildOfClass("BasePart")
end
elseif instance:IsA("Model") then
if instance.PrimaryPart then
return instance.PrimaryPart
else
return instance:FindFirstChildOfClass("BasePart")
end
end
end
end
function aware.get.nearest(list, root, dist, getone, mode)
local a = root.Position
local b = nil
--local c = nil
--local d = nil
--local e = nil
local f = 0
local g = nil
local range=dist
-- local list=list
local arealist={}
local root_forward = root.CFrame.LookVector -- get the root's forward vector
local root_forwardX =root_forward.X
local root_forwardY=root_forward.Y
local root_forwardZ=root_forward.Z
if list ~= nil then
for h = 1, #list do
-- e = list[h]
local c= aware.get.root2(list[h])
-- if e.Parent==plan then if c:FindFirstChild("Species") then c=nil end end
if c and root ~= c then
local root_to_object = (c.Position - a)
local calc = root_to_object.Magnitude
if calc< range then
if getone=="array" then
table.insert(arealist,{maininstance=list[h],instance=c,size=g,distance=calc})
end
if getone=="chatgpt" then
--local judgeobj=list[h]
local judgeobj= game.ReplicatedStorage.Items.Plants:FindFirstChild(tostring(list[h]))
if judgeobj then
else
judgeobj=list[h]
end
table.insert(arealist,{model=list[h],primary=c,name=aware.judge.object(judgeobj),position=c.Position,distance=calc})
end
if calc < dist then --and dot_product > 0 then -- check if the object is in front of the root variable
-- get the vector from the root to the objec
local dot_product = root_forwardX * root_to_object.X + root_forwardY * root_to_object.Y + root_forwardZ * root_to_object.Z -- calculate the dot product
if dot_product >0 then
f = f + 1
if mode==nil or mode==false then
b = c
elseif mode==true then
b = list[h]
elseif mode.Query~=nil and query(mode.Query,aware.judge.object(list[h]):lower())~=nil then
print("Got match"..mode.Query..aware.judge.object(list[h]):lower())
b = list[h]
end
dist = calc
g = c.Size
if getone == true then
return b, g, calc
end
end
end
end
end
end
end
if #list > 30 then
task.wait()
-- if #list > 30 then
-- task.wait(.6)
-- end
end
if getone=="array" then
table.sort(arealist,function(a,b) return a.distance>b.distance end)
end
return b, f, g, dist,arealist
end
function aware.get.nearestModels(root,radius,getone,mode)--get the nearest object of each type
local objectmegaarray={}
--local numberofobjects=0
local numberofclasses=0
for i,v in aware.near do
local _,_,_,_,objectarray=aware.near[i](root,radius,getone,mode)
if objectarray then
local num=#objectarray
if num>=1 then
numberofclasses+=1
end
end
-- numberofobjects+=num
objectmegaarray[i]=objectarray
end
local numberclass=math.min(1,7/numberofclasses)
local organizedobjects={}
--table.sort(organizedobjects,function(a,b)return a.distance<b.distance end)
for i,objectarray in objectmegaarray do
for t,o in objectarray do
if t<=numberclass then --get 3 objects max
table.insert(organizedobjects,o)
else
break
end
end
end
table.sort(organizedobjects,function(a,b) return a.distance<b.distance end)
return organizedobjects
end
function aware.get.terrain(root,radius,str)
local phrases = {
"The environment has",
"The terrain consists of",
"The surroundings a characterized by",
"The landscape features",
"The ecosystem hosts",
}
if radius~=true then
if str~="" and string.gmatch(str, "%w+") and string.len(str)>4 then
--rewrite the table in the first person context
return phrases[aware.quoterandom(1,#phrases)].." "..str..". "
end
local terrianjudge=aware.judge.terrain(root,radius)
if terrianjudge~=nil and terrianjudge~="" and string.gmatch(terrianjudge, "%w+") and string.len(terrianjudge)>4 then
return phrases[aware.quoterandom(1,#phrases)].." "..terrianjudge..". "
else
return nil
end
elseif radius==true then
return phrases[aware.quoterandom(1,#phrases)]:lower().." "..str..""
end
end
function aware.get.walking(root,player,walkings)
local hum
if root.Parent:FindFirstChild("Humanoid") then
hum=root.Parent.Humanoid
else
hum=player.Character.Humanoid
end
local floormat = hum.FloorMaterial
local walking="standing" if root.Velocity.Magnitude>1 then walking="walking" end
if not floormat then floormat = 'Air'
return nil
end
local matstring = string.split(tostring(floormat),'Enum.Material.')[2]
--
if matstring~='Air' and matstring~='Plastic' and matstring~="SmoothPlastic" and matstring~="Neon" then
if matsolutions[matstring]~=nil then
matstring= matsolutions[matstring]
end
local material = "I am "..walking.." on "..matstring:lower()..""
return material
else
if matstring=="Plastic" or matstring=="SmoothPlatstic" then
local matstring=player.PlayerGui.Chatbot.FloorPlatform.Value
if matstring~="" then
return "I am "..walking.." on a "..matstring:lower()..""
else
if walking then
return "I am "..walking..""
end
end
end
return ""
end
end
function aware.get.objectsdata(root,key,mode,getone)
if key==nil then
if awarekeys["objective"]["datatable"] == nil or
awarekeys["objective"]["writetime"] + awarekeys["observations"]["refreshrate"] < os.time() or root~=previousroot
then
closestPlant, numPlants, plantsize, plantdist = aware.near.plant(root, 40,getone)
closestTree, numTrees, treesize, treedist = aware.near.tree(root, 80,getone)
closestStructure, numStructures, structuresize, strucdist = aware.near.structure(root, 160,getone)
closestEnemy, numEnemies, enemysize, enemydist = aware.near.enemys(root, 60,getone)
closestNPC, numNPCs, npcsize, npcdist = aware.near.npcs(root, 80,getone)
closestPlayer, numPlayers, plrsize, plrdist = aware.near.player(root, 80,getone)
closestRubble, numRubble, rubblesize, rubbledist = aware.near.rubble(root, 20,getone)
closestChest, numChests, chestsize, chestdist = aware.near.chest(root, 30,getone)
closestGroundItem, numGroundItems, itemsize, itemdist = aware.near.loot(root, 40,getone)
closestHouse, numHouses, housesize, housedist = aware.near.house(root, 100,getone)
closestDungeon, numDungeons, dungsize, dungdist = aware.near.dungeons(root, 200,getone)
closestFish, numFish, Fishsize, Fishdist = aware.near.fish(root, 120,getone)
closestFurn, numFurn, Furnsize, Furndist,Furnarray = aware.near.furniture(root, 80,getone)
objecttable={
Plant={Close=closestPlant,Amount=numPlants,Size=plantsize,Distance=plantdist},
Tree={Close=closestTree,Amount=numTrees,Size=treesize,Distance=treedist},
Structure={Close=closestStructure,Amount=numStructures,Size=structuresize,Distance=strucdist},
Enemy={Close=closestEnemy,Amount=numEnemies,Size=enemysize,Distance=enemydist},
NPC={Close=closestNPC,Amount=numNPCs,Size=npcsize,Distance=npcdist},
Player={Close=closestPlayer,Amount=numPlayers,Size=plrsize,Distance=plrdist},
Rubble={Close=closestRubble,Amount=numRubble,Size=rubblesize,Distance=rubbledist},
Chest={Close=closestChest,Amount=numChests,Size=chestsize,Distance=chestdist},
Item={Close=closestGroundItem,Amount=numGroundItems,Size=itemsize,Distance=itemdist},
House={Close=closestHouse,Amount=numHouses,Size=housesize,Distance=housedist},
Area={Close=closestDungeon,Amount=numDungeons,Size=dungsize,Distance=dungdist},
Fish={Close=closestFish,Amount=numFish,Size=Fishsize,Distance=Fishdist},
Furniture={Close=closestFurn,Amount=numFurn,Size=Furnsize,Distance=Furndist,Array=Furnarray},
}
awarekeys["objective"] = {["datatable"] = nil, ["writetime"] = os.time(), ["refreshrate"] = 10}
end
else
if mode==nil then mode=false end
if key=="plant" then return aware.near.plant(root, 40,getone,mode)
elseif key=="tree" then return aware.near.tree(root, 80,getone,mode)
elseif key=="structure" then return aware.near.structure(root, 160,getone,mode)
elseif key=="enemy" then return aware.near.enemy(root, 60,getone,mode)
elseif key=="npcs" then return aware.near.npcs(root, 80,getone,mode)
elseif key=="players" then return aware.near.player(root, 80,getone,mode)
elseif key=="rubble" then return aware.near.rubble(root, 20,getone,mode)
elseif key=="chests" then return aware.near.chest(root, 30,getone,mode)
elseif key=="loot" then return aware.near.loot(root, 40,getone,mode)
elseif key=="houses" then return aware.near.house(root, 100,getone,mode)
elseif key=="dungeons" then return aware.near.dungeons(root, 200,getone,mode)
elseif key=="fish" then return aware.near.fish(root, 240,getone,mode)
elseif key=="furniture" then return aware.near.furniture(root, 60,getone,mode) end
end
return objecttable
end
function aware.judge.amnt(amnt,judgeme,judgeamntdistribution)
if judgeamntdistribution==nil then judgeamntdistribution=judgeamntdistributio end
--print(amnt)
local index = 1
repeat
if amnt <= judgeamntdistribution[index] then
if judgeme then return judgeme[index][aware.quoterandom(1,#judgeme[index])] else return judgeamntstrings[index][1] end -- do not duplicate the table
end
index = index + 1
until index >= #judgeamntdistribution
return toomany[aware.quoterandom(1,3)]
end
function aware.judge.thing(size, bigSize, judgeSizes, judgeStrings)
local index = 1
local sizeJudge = ""
if typeof(size) == "Vector3" then
for i, judge in ipairs(judgeSizes) do
if size <= bigSize * judge then
local sizeJudge2 = judgeStrings[i]
sizeJudge = sizeJudge2[aware.mathrandom(1, #sizeJudge)]
break
end
end
else
for i, judge in ipairs(judgeSizes) do
if size <= bigSize * judge then
local sizeJudge2 = judgeStrings[i]
sizeJudge = sizeJudge2[aware.mathrandom(1, #sizeJudge)]
break
end
end
end
return sizeJudge
end
function aware.judge.size(size, bigSize)
local size = size.X + size.Y + size.Z
local bigSize = bigSize.X + bigSize.Y + bigSize.Z
local sizeJudge = aware.judge.thing(size, bigSize, judgematrixSizes, judgematrixStrings)
return sizeJudge
end
function aware.judge.rubble(size, bigSize)
if size and bigSize then
local size = size.X + size.Y + size.Z
local bigSize = bigSize.X + bigSize.Y + bigSize.Z
local sizeJudge = aware.judge.thing(size, bigSize, rockjudgematrixSizes, rockpiece)
return sizeJudge
else return rockpiece[aware.quoterandom(1,#rockpiece)]
end
end
function aware.judge.height(size, bigSize)
return aware.judge.thing(size, bigSize, heightmatrixSizes , heightmatrixstrings)
end
function aware.judge.power(power, bigpower)
local sizeJudge = aware.judge.thing(power, bigpower, judgepowerSizes, judgepowerStrings)
return sizeJudge
end
function aware.judge.object(instance, itself)--implementation of a custom naming system
if instance ~= nil then
if instance.Parent then
if instance.Parent==workspace.Rubble then
return aware.judge.rubble(Instance.Size, Vector3.new(10,10,10))
-- elseif
end
end
local s = instance:FindFirstChild("Species")
if s then return s.Value end
local selfrecog = nil
if instance == itself then
selfrecog = "I am"
end
if instance:FindFirstChild("Humanoid") ~= nil then
return instance.Humanoid.DisplayName
elseif instance:IsA("BasePart") then
local s = instance:FindFirstChild("Species")
if s ~= nil then
return s.Value
elseif instance.Parent and instance.Parent:FindFirstChild("Humanoid") ~= nil then
return instance.Parent.Humanoid.DisplayName
elseif string.find(instance.Name,"Rock") then
return rockpiece[aware.quoterandom(1,#rockpiece)]
end
--elseif instance:IsA("Folder") ~= nil then
-- -- return instance.Name
--elseif instance:IsA("Model") then
-- return instance.Name
end
--return instance.Name
-- end
end
return tostring(instance)
end
function aware.judge.item(instance)
if instance ~= nil then
if instance.Parent then
local selfrecog = nil
if instance:FindFirstChild("Humanoid") ~= nil then
return instance.Humanoid.DisplayName
elseif instance:IsA("BasePart") then
local s = instance:FindFirstChild("Species")
if s ~= nil then
return s.Value
elseif instance.Parent:FindFirstChild("Humanoid") ~= nil then
return instance.Parent.Humanoid.DisplayName
else return instance.Name
end
elseif instance:IsA("Folder") ~= nil then
return instance.Name
elseif instance:IsA("Model") then
return instance.Name
end
end
end
return nil
end
function aware.judge.distance(root, magnitude, position, position2, maxDist)
local dirName = ""
local distanceJudge = ""
if position ~= position2 then
local distVector = magnitude
local judgedDist = {0.2, 0.4, 0.6, 0.8, 1, 1.5, 2}
local judgeStrings = {
{"very close", "quite nearby", "within reach", "pretty close", "a stone's throw away"},
{"close", "nearby", "a short distance away", "close by", "not far off"},
{"kind of close", "not too far", "moderately near", "fairly close", "somewhat near"},
{"not far", "within sight", "a reasonable distance away", "not too distant"},
{"kinda far", "some distance away", "somewhat distant", "a bit far"},
{"far", "a long distance away", "quite some ways away", "far away"},
{"very far", "very distant", "quite far"}
}
local index = 1
if maxDist~=nil then
repeat
if index<= #judgedDist then if distVector <= maxDist * judgedDist[index] then
if distVector > 1 then
distanceJudge = judgeStrings[index][1]
else
distanceJudge = "right here"
end
break
end end
index = index + 1
until index >= #judgedDist
else
maxDist=50
distanceJudge="Distance Error"
return "Distance Error" ,"Error"
end
-- Get direction
--local rootfront=root.CFrame:ToWorldSpace(CFrame.new(0,0,))
local dif=(position2 - position)
local tolerance = 10 -- define the tolerance value
local ydifference = position2.Y - position.Y
if distanceJudge~="" and distanceJudge~=nil and ydifference~=nil then
if ydifference > tolerance or ydifference < -tolerance then -- compare with the tolerance value
local heightjudge=aware.judge.height(ydifference, 80)
if heightjudge then
distanceJudge = distanceJudge .. " "..heightjudge.."me"
end
end
end
local dirVector = dif.Unit -- Unit vector pointing to position2
local angle = math.atan2(dirVector.Z, dirVector.X) -- Angle in radians
--local dirName = ""
local leftright=maxDist*.15
if magnitude>=leftright then
if distanceJudge ~= "right here" then
if angle > math.rad(157.5) or angle < math.rad(-157.5) then
dirName = "south"
elseif angle > math.rad(112.5) then
dirName = "southwest"
elseif angle > math.rad(67.5) then
dirName = "west"
elseif angle > math.rad(22.5) then
dirName = "northwest"
elseif angle > math.rad(-22.5) then
dirName = "north"
elseif angle > math.rad(-67.5) then
dirName = "northeast"
elseif angle > math.rad(-112.5) then
dirName = "east"
else
dirName = "southeast"
end
dirName=" to the "..dirName
else
dirName = " at the current position"
end
else dirName=" "..aware.judge.rightfront(root,position2)
end
else
dirName = " at the current position"
distanceJudge = " right here"
end
if dirName==nil then
dirName=""
distanceJudge=""
end
if distanceJudge==nil then
distanceJudge=""
end
return distanceJudge, dirName
end
function aware.judge.rightfront(obj1, position2)
-- First, we need to convert the position2object space of obj1
-- This means that we will get a new Vector3 value that is relative to the center and orientation of obj1
-- We can use the ToObjectSpace method of the CFrame class to do this
local relativePosition = obj1.CFrame:ToObjectSpace(CFrame.new(position2)).Position
-- Next, we need to get the half size of obj1 along each axis
-- This will help us determine if the position2 is inside or outside the bounding box of obj1
local halfSize = obj1.Size * 0.5
-- Now, we can use some simple logic to classify the relative position
-- We will use four variables to store the possible directions: left, right, front, and back
local left, right, front, back = false, false, false, false
-- We will check each axis separately and set the corresponding variables to true if the condition is met
-- For the x-axis, we will use the left and right directions
-- If the relative position is less than the negative half size, it means it is to the left of obj1
-- If the relative position is greater than the positive half size, it means it is to the right of obj1
if relativePosition.X < -halfSize.X then
left = true
elseif relativePosition.X > halfSize.X then
right = true
end
-- For the z-axis, we will use the front and back directions
-- If the relative position is less than the negative half size, it means it is behind obj1
-- If the relative position is greater than the positive half size, it means it is in front of obj1
if relativePosition.Z < halfSize.Z then
back = true
elseif relativePosition.Z > -halfSize.Z then
front = true
end
-- For the y-axis, we will ignore it for now, since we are only interested in the horizontal directions
-- However, if you want to include the up and down directions, you can use a similar logic as above
-- Finally, we will construct the output string based on the variables we set
-- We will use a table to store the possible directions and concatenate them with commas
local output = {}
-- We will use a simple if-else statement to check each variable and add the corresponding direction to the table
-- We will also use the plural form if there are more than one direction
if back then
table.insert(output, "behind me")
elseif front then
table.insert(output, "in front of me")
end
if left then
table.insert(output, " to the left")
elseif right then
table.insert(output, " to the right")
end
-- If the output table is empty, it means that the position2 is inside or on the edge of the bounding box of obj1
-- In that case, we will return a special message
if #output == 0 then
return "before me"--"The position is inside or on the edge of the object"
end
-- Otherwise, we will join the table elements with commas and return the final string
return table.concat(output, "")
end
function aware.judge.terrain(root,radius)
local function detecter(material)
local materel={}
--print(material)
local nummats=0
for i,v in material do
if material[i] then
if i~="Size" then
--if material[i][1] then
for t,o in material[i] do
for c,p in material[i][t] do
--if --material[i][t][c]~=Enum.Material.Water and
if material[i][t][c]~=Enum.Material.Air then --count all of the terrain
local matstring = string.split(tostring(material[i][t][c]),'Enum.Material.')[2]
if matsolutions[matstring]~=nil then
matstring= matsolutions[matstring]
end
if materel[matstring]==nil then
nummats+=1
materel[matstring]=1
else
materel[matstring]+=1
--table.sort(materel,function(a,b)return a>b end)--sort greatest to
end
--return true
end
end
end
end
end
end
--least
--print(materel)
--create an array with the keys
local keys = {}
for k in pairs(materel) do
table.insert(keys, k)
end
--sort the array using a custom comparison function
table.sort(keys, function(a, b) return materel[a] < materel[b] end)
--print the sorted table
--table.sort(materel,function(a,b)return a>b end)--sort greatest to
--table.sort(materel,function(a,b)return a>b end)--sort greatest to least
local judgeamntstrings = {
{"a handful of", "a few", "a smattering of", "a sprinkling of"},
{"a little bit of", "a trace of", "a touch of", "a dash of"},
{"a sparse amount of", "a scant amount of", "a meager amount of", "a minimal amount of"},
{"bunches of", "clusters of", "groups of", "packs of"},
{"a lot of", "heaps of", "a ton of", "loads of"},
{"a multitude of", "a plethora of", "hordes of", "heaps of"},
{"a huge quantity of", "a massive amount of", "a colossal amount of", "a prodigious amount of"},
{"a staggering number of", "an astonishing number of", "a phenomenal number of", "a mind-blowing number of"}
}
local judgementstring=""
local index=0
--{1, 2, 3, 4, 5, 6, 8}
local judgmatrix={1,radius,radius*2,radius*3,radius*4,radius*4.5,radius*4.75,radius*5}
--for i, k in ipairs(keys) do
-- print(k,)
--end
for i,k in keys do
index=index+1
if index==nummats and index>1 then
judgementstring..="and "
end
judgementstring..=aware.judge.amnt(materel[k],judgeamntstrings,judgmatrix).." "..k:lower()
if index~= nummats then
judgementstring..=", "
end
end
return judgementstring
end
if root then
local region = Region3.new(root.Position-Vector3.new(radius,8+root.Size.Y,radius),root.Position+Vector3.new(radius,radius,radius))
local material = terrain:ReadVoxels(region, 4)
-- detecter(material)
--phraselib.opener[aware.mathrandom(1,#phraselib.opener)]
return detecter(material)
end
end
function aware.judge.water(root)
-- Loop through the directions and cast rays
local origin=root.CFrame:ToWorldSpace(CFrame.new(0,5,0)).Position--go above the part to get a better angle
for i, dir in ipairs(waterdirections) do
local result = workspace:Raycast(origin, dir, params)
-- Check if the ray hit anything
if result then
-- Check if the hit part is water terrain
if result.Instance:IsA("Terrain") and result.Material == Enum.Material.Water then
local magn=(origin-result.Position).Magnitude
local dist, dir = aware.judge.distance(root,magn, origin, result.Position, range)
return phraselib.waterdescription[aware.quoterandom(1,#phraselib.waterdescription)] .. dist .. " to the " .. dir.."",magn
end
end
end
return "",nil
end
function aware.judge.distribution(number,matrixSizes,matrixStrings)
-- Loop through the matrix of height distributions
for i = 1, #matrixSizes do
-- Find the index where the number is less than or equal to the matrix value
if number <= matrixSizes[i] or i==#matrixSizes then
-- Return the string at that index
return matrixStrings[i][1]
end
end
end
function aware.judge.human.thickness(number)
return aware.judge.distribution(number,judgethicknessmatrixSizes,judgethicknessmatrixStrings)
end
function aware.judge.human.size(number)
return aware.judge.distribution(number,jmatrixSizes,judgehsizematrixStrings)
end
function aware.judge.human.width(number)
return aware.judge.distribution(number,jmatrixSizes,judgewidthmatrixStrings)
end
function aware.judge.human.height(number)
return aware.judge.distribution(number, judgeheightmatrixSizes , judgehmatrixStrings)
end
function aware.judge.human.description(humanoid,completeresponse,tenses)
if humanoid:FindFirstChild("BodyHeightScale") then
local vars={
humanoid["BodyTypeScale"].Value,
humanoid["BodyProportionScale"].Value,
humanoid["BodyWidthScale"].Value,
humanoid["BodyHeightScale"].Value,
humanoid["BodyDepthScale"].Value,
humanoid["HeadScale"].Value
}
local Skincolor=humanoid.Parent:FindFirstChild("Inventory")
if Skincolor then
Skincolor=Skincolor.SkinColor.Value
if tenses==nil then
Skincolor="My skin is "..Skincolor.." in color, "
else
Skincolor="Your skin is "..Skincolor.." in color, "
end
end
if tenses==nil then tenses={"I am ","I have a "} end
local descguide= {
-- ["BodyTypeScale"],
-- ["BodyProportionScale"],
["BodyWidthScale"]=function () return tenses[1],aware.judge.human.width(vars[3]).." in the hips" end,
["BodyHeightScale"]=function () return tenses[1],aware.judge.human.height(vars[4]).." in height" end,
["BodyDepthScale"]=function () return tenses[1],aware.judge.human.thickness(vars[5]).." in the waist" end,
["HeadScale"]=function () return tenses[2],aware.judge.human.size(vars[6]).." head" end,
}
local response={[1]=""}
if completeresponse==nil then completeresponse="If I were to describe my figure I would say," end
for i,v in descguide do
local v1,v2=descguide[i]()
table.insert(response, v1..v2..".")
if v1=="I am " then
completeresponse=completeresponse.." "..v2..","
else
completeresponse=completeresponse.." "..v1..v2.."."
end
end
response[1]=completeresponse
if Skincolor then
response[1]=Skincolor..completeresponse
end
return response
else
return {[1]=""}
end
end
function aware.judge.human.outfit(npc,tense,player)
--aware.judge.human.Equipment(npc)
if tense==nil then tense="I am wearing a" end
local str=tense
local invent=getinvent(npc,player)
if invent then
local customc=invent.CustomCharacter
local topclothes=invent.TopClothes
local bottomclothes=invent.PantSkirtDress
if topclothes.Value~=customc.Value and string.len(topclothes.Value)>3 then -- would imply not wearing an outfit
str=str.." "..topclothes.Value
if bottomclothes.Value~=customc.Value and string.len(bottomclothes.Value)>3 then -- would imply not wearing an outfit
str=str.." and a "..bottomclothes.Value..". "
else
str=str..". "
end
elseif bottomclothes.Value~=customc.Value and string.len(bottomclothes.Value)>3 then
str=str.." "..bottomclothes.Value..". "
end
end
if str~=tense then
return str
else
return ""
end
end
function aware.judge.human.Equipment(npc,player,reflect)
if player:FindFirstChild("Inventory")~=nil then
local equipmentarray={
["Armor"]={"my armor is called "},
["Amulet"]={"I'm wearing a "," around my neck"},
["Book"]={"I have this magic tome called "},
["Cape"]={"I have a cape called "," on my back"},
["Boots"]={"I'm wearing "," on my feet"},
["Helmet"]={"I have a "," over my head"},
["Shield"]={"my shield is called "},
["Sword"]={"my sword is called the "},
["Gun"]={"I own a "},
["Wand"]={"my magic wand is called the "},
["Bracelet"]={"I'm wearing a "," on my wrist"}
}
local theirequipmentarray={
["Armor"]={"their armor is called "},
["Amulet"]={"they are wearing a "," around their neck"},
["Book"]={"they have this magic tome called "},
["Cape"]={"they have a cape called "," on their back"},
["Boots"]={"they're wearing "," on their feet"},
["Helmet"]={"they have a "," over their head"},
["Shield"]={"their shield is called "},
["Sword"]={"their sword is called the "},
["Gun"]={"they own a "},
["Wand"]={"their magic wand is called the "},
["Bracelet"]={"they are wearing a "," on their wrist"}
}
local yourequipmentarray={
["Armor"]={"your armor is called "},
["Amulet"]={"you are wearing a "," around your neck"},
["Book"]={"you have that magic tome called "},
["Cape"]={"you have a cape called "," on your back"},
["Boots"]={"you're wearing "," on your feet"},
["Helmet"]={"you have a "," over your head"},
["Shield"]={"your shield is called "},
["Sword"]={"your sword is called the "},
["Gun"]={"you own a "},
["Wand"]={"your magic wand is called the "},
["Bracelet"]={"you are wearing a "," on your wrist"}
}
local equipmentdescriptions={}
local str="I have an array of equipment"
local invent =getinvent(npc,player)
local invent2=player.Inventory
local theirstr="I can see that "..tostring(player).." has equipment"
local gotequipment=false
if reflect then
equipmentarray=theirequipmentarray
str=theirstr
end
if invent then
--local c=0
for i,v in equipmentarray do
-- c+=1
if invent[i]~=nil then
local item=invent[i].Value
if item~="" and item~=nil and string.len(item)>3 then
if i=="Wand" or i=="Shield" then
item=modify_string(item)
end
gotequipment=true
if #v==2 then
str=str..", "..v[1]..item..""..v[2]
table.insert(equipmentdescriptions,aware.cap(v[1])..item..""..v[2]..".")
else
str=str..", "..v[1]..item..""
table.insert(equipmentdescriptions,aware.cap(v[1])..item..".")
end
end
end
end
if gotequipment then
str=str..". "
table.insert(equipmentdescriptions,str)
return equipmentdescriptions,str
end
end
end
return {},""
end
function aware.near.boid(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("boid"), root, dist, getone, mode)
end
function aware.near.furniture(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("furniture"), root, dist, getone, mode)
end
function aware.near.rubble(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("rubble"), root, dist, getone, mode)
end
function aware.near.plant(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("plants"), root, dist, getone, mode)
end
function aware.near.crystal(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("crystal"), root, dist, getone, mode)
end
function aware.near.tree(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("trees"), root, dist, getone, mode)
end
function aware.near.house(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("houses"), root, dist, getone, mode)
end
function aware.near.dungeons(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("dungeons"), root, dist, getone, mode)
end
function aware.near.chest(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("chests"), root, dist, getone, mode)
end
function aware.near.mapobj(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("mapobject"), root, dist, getone, mode)
end
function aware.near.loot(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("grounditems"), root, dist, getone, mode)
end
function aware.near.NPC(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("npcs"), root, dist, getone, mode)
end
function aware.near.Enemy(root, dist, getone,mode)
if mode==nil then mode=true end
--local enemys =
return aware.get.nearest(aware.Gettable("enemys"), root, dist, getone, mode)
end
function aware.near.player(root, dist, getone,mode)
if mode==nil then mode=true end
return aware.get.nearest(aware.Gettable("players"), root, dist, getone, mode)
end
function aware.near.fish(root, dist, getone,mode)
if mode==nil then mode=true end
if root.Position.Y<=-16 then--if root is lower than the water line
return aware.get.nearest(aware.Gettable("fish"), root, dist, getone, mode)
else return nil,0,nil,nil
end
end
local ranges={}
function aware.quoterandom(min,max)--tries not to repeat concurrent rolls
if max==nil then
max=min
min=1
end
if max>=3 then
local key=tostring(min..","..max)
if ranges[key]==nil then
ranges[key]=math.random(min,max)
else
local previous=ranges[key]
local roll=math.random(min,max)
if roll==previous then
roll=math.random(min,max)
if roll==previous then
roll=math.random(min,max)
end
end
ranges[key]=roll
end
return ranges[key]
else
return math.random(min,max)
end
end
–Excluding Main Function to not exceed post character limit