Initial commit, all scripts and esp

This commit is contained in:
Tyler Hallada 2020-10-12 21:26:16 -04:00
commit 6cdd85a866
48 changed files with 1390 additions and 0 deletions

12
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
// created by vscode papyrus-lang papyrus.skyrimSpecialEdition.generateProject
"version": "0.2.0",
"configurations": [
{
"name": "Skyrim SE",
"type": "papyrus",
"request": "attach",
"game": "skyrimSpecialEdition"
}
]
}

19
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,19 @@
{
// created by vscode papyrus-lang papyrus.skyrimSpecialEdition.generateProject
"version": "2.0.0",
"tasks": [
{
"type": "pyro",
"projectFile": "skyrimse.ppj",
"gamePath": "e:\\Program Files (x86)\\Steam\\steamapps\\common\\Skyrim Special Edition",
"problemMatcher": [
"$PapyrusCompiler"
],
"label": "pyro: Compile Project (skyrimse.ppj)",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

BIN
Bazaar Realm.esp Normal file

Binary file not shown.

BIN
Scripts/BRClient.pex Normal file

Binary file not shown.

Binary file not shown.

BIN
Scripts/BRMCMConfigMenu.pex Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Scripts/BRMerchandise.pex Normal file

Binary file not shown.

Binary file not shown.

BIN
Scripts/BROwner.pex Normal file

Binary file not shown.

Binary file not shown.

BIN
Scripts/BRQuestScript.pex Normal file

Binary file not shown.

BIN
Scripts/BRShop.pex Normal file

Binary file not shown.

Binary file not shown.

BIN
Scripts/CMFetchThread.pex Normal file

Binary file not shown.

BIN
Scripts/CMFetchThread01.pex Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

13
SkyrimSE.code-workspace Normal file
View File

@ -0,0 +1,13 @@
{
// created by vscode papyrus-lang papyrus.skyrimSpecialEdition.generateProject
"folders": [
{
"path": "."
}
],
"settings": {
"papyrus.skyrimSpecialEdition.enabled": true,
"papyrus.fallout4.enabled": false,
"papyrus.skyrim.enabled": false
}
}

View File

@ -0,0 +1,5 @@
scriptname BRClient
function Init() global native
bool function StatusCheck(string apiKey) global native
string function GenerateApiKey() global native

View File

@ -0,0 +1,5 @@
scriptname BRInteriorRefList
int function Create(string apiUrl, string apiKey, int shop_id, cell cell) global native
bool function ClearCell(cell cell) global native
bool function Load(string apiUrl, string apiKey, int interior_ref_id, cell cell, ObjectReference player) global native

View File

@ -0,0 +1,129 @@
scriptname BRMCMConfigMenu extends SKI_ConfigBase
BRQuestScript property BR auto
bool modStarted = false
int function GetVersion()
return 1
endFunction
event OnPageReset(string page)
SetCursorFillMode(LEFT_TO_RIGHT)
AddHeaderOption("Server Config")
SetCursorPosition(2)
AddTextOptionST("SERVER_URL_LABEL", "API Server URL: ", "", OPTION_FLAG_DISABLED)
if modStarted
AddInputOptionST("SERVER_URL_VALUE", "", BR.ApiUrl, OPTION_FLAG_DISABLED)
else
AddInputOptionST("SERVER_URL_VALUE", "", BR.ApiUrl)
endif
if modStarted
AddTextOptionST("API_KEY", "Reveal API key", "")
endif
SetCursorPosition(7)
if modStarted
AddToggleOptionST("START_MOD", "Mod Started", modStarted, OPTION_FLAG_DISABLED)
else
AddToggleOptionST("START_MOD", "Start Mod", modStarted)
endif
AddHeaderOption("Shop Actions")
SetCursorPosition(10)
AddTextOptionST("SAVE_REFS", "Save current shop state", "")
AddTextOptionST("LOAD_REFS", "Load saved shop state", "")
AddTextOptionST("LIST_MERCH", "Show shop merchandise", "")
AddTextOptionST("LOAD_MERCH", "Load shop merchandise", "")
endEvent
state SERVER_URL_VALUE
event OnInputOpenST()
SetInputDialogStartText(BR.ApiUrl)
endEvent
event OnInputAcceptST(string textInput)
BR.ApiUrl = textInput
SetInputOptionValueST(textInput)
endEvent
event OnHighlightST()
SetInfoText("The Bazaar Realm Server URL. Leave this at the default value to play on the main server with other players. If you would like to use your own private server, read the README for instructions on how to set one up, and then set this value to your server's URL.")
endEvent
event OnDefaultST()
BR.ApiUrl = "https://api.bazaarrealm.com"
SetInputOptionValueST(BR.ApiUrl)
endEvent
endState
state API_KEY
event OnHighlightST()
SetInfoText("Click to see your unique server API key. Keep it secret since it allows modifying your shop data.")
endEvent
event OnSelectST()
ShowMessage(BR.ApiKey)
endEvent
endState
state START_MOD
event OnSelectST()
if BR.StartMod()
modStarted = true
SetToggleOptionValueST(true, true)
SetOptionFlagsST(OPTION_FLAG_DISABLED, true)
SetOptionFlagsST(OPTION_FLAG_DISABLED, true, "SERVER_URL_VALUE")
endif
ForcePageReset()
endEvent
event OnHighlightST()
SetInfoText("Starts the mod on the configured server. WARNING: You cannot change the server URL once the mod is started.")
endEvent
endState
state SAVE_REFS
event OnSelectST()
if BR.SaveInteriorRefs()
debug.MessageBox("Successfully saved shop.")
endif
endEvent
event OnHighlightST()
SetInfoText("If you are currently in your shop, clicking this will save the current state of its interior to the server.")
endEvent
endState
state LOAD_REFS
event OnSelectST()
if BR.LoadInteriorRefs()
debug.MessageBox("Successfully loaded shop.")
endif
endEvent
event OnHighlightST()
SetInfoText("If you are currently in your shop, clicking this will load the last saved state of its interior from the server.")
endEvent
endState
state LIST_MERCH
event OnSelectST()
BR.ListMerchandise()
endEvent
event OnHighlightST()
SetInfoText("Open a list of every item currently up for sale in your shop's merchandise inventory.")
endEvent
endState
state LOAD_MERCH
event OnSelectST()
BR.LoadMerchandise()
endEvent
event OnHighlightST()
SetInfoText("Load shop merchandise onto the merchant shelf of the shop.")
endEvent
endState

View File

@ -0,0 +1,28 @@
Scriptname BRMerchChestScript extends ObjectReference
Actor Property PlayerRef Auto
Quest Property BRQuest Auto
event OnMenuClose(string menuName)
if menuName == "ContainerMenu"
debug.Trace("Peddling container menu closed")
BRQuestScript BRScript = BRQuest as BRQuestScript
int result = BRMerchandiseList.Create(BRScript.ApiUrl, BRScript.ApiKey, BRScript.ShopId, self)
if result == -2
Debug.Trace("No container changes to save to the server")
elseif result == -1
Debug.MessageBox("Failed to save shop merchandise. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
else
BRScript.MerchandiseListId = result;
Debug.Notification("Saved merchandise successfully")
endif
UnregisterForMenu("ContainerMenu")
endif
endEvent
event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
debug.Trace("Peddling container was opened")
RegisterForMenu("ContainerMenu")
endif
endEvent

View File

@ -0,0 +1,28 @@
scriptname BRMerchNextPageScript extends ObjectReference
Keyword property BRLinkMerchShelf auto
Keyword property BRLinkMerchChest auto
Keyword property BRLinkItemRef auto
Keyword property BRLinkMerchToggle auto
Keyword property BRLinkMerchNext auto
Keyword property BRLinkMerchPrev auto
Activator property PlaceholderStatic auto
Actor property PlayerRef auto
Quest Property BRQuest Auto
Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
ObjectReference MerchantShelf = self.GetLinkedRef(BRLinkMerchShelf)
BRQuestScript BRScript = BRQuest as BRQuestScript
bool result = BRMerchandiseList.NextPage(BRScript.ApiUrl, BRScript.ApiKey, BRScript.MerchandiseListId, MerchantShelf, PlaceholderStatic, BRLinkMerchShelf, BRLinkMerchChest, BRLinkItemRef, BRLinkMerchToggle, BRLinkMerchNext, BRLinkMerchPrev)
debug.Trace("BRMerchandiseList.NextPage result: " + result)
if result
while !BRMerchandiseList.Replace3D(MerchantShelf, PlaceholderStatic, BRLinkMerchShelf, BRLinkItemRef)
Debug.Trace("BRMerchandiseList.Replace3D returned false, waiting and trying again")
Utility.Wait(0.05)
endWhile
else
Debug.MessageBox("Failed to load shop merchandise. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
endif
endif
EndEvent

View File

@ -0,0 +1,10 @@
scriptname BRMerchPlaceholderScript extends ObjectReference
Actor Property PlayerRef Auto
Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
Form merch = BRMerchandiseList.Buy(self)
PlayerRef.AddItem(merch, 1)
endif
EndEvent

View File

@ -0,0 +1,28 @@
scriptname BRMerchPrevPageScript extends ObjectReference
Keyword property BRLinkMerchShelf auto
Keyword property BRLinkMerchChest auto
Keyword property BRLinkItemRef auto
Keyword property BRLinkMerchToggle auto
Keyword property BRLinkMerchNext auto
Keyword property BRLinkMerchPrev auto
Activator property PlaceholderStatic auto
Actor property PlayerRef auto
Quest Property BRQuest Auto
Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
ObjectReference MerchantShelf = self.GetLinkedRef(BRLinkMerchShelf)
BRQuestScript BRScript = BRQuest as BRQuestScript
bool result = BRMerchandiseList.PrevPage(BRScript.ApiUrl, BRScript.ApiKey, BRScript.MerchandiseListId, MerchantShelf, PlaceholderStatic, BRLinkMerchShelf, BRLinkMerchChest, BRLinkItemRef, BRLinkMerchToggle, BRLinkMerchNext, BRLinkMerchPrev)
debug.Trace("BRMerchandiseList.PrevPage result: " + result)
if result
while !BRMerchandiseList.Replace3D(MerchantShelf, PlaceholderStatic, BRLinkMerchShelf, BRLinkItemRef)
Debug.Trace("BRMerchandiseList.Replace3D returned false, waiting and trying again")
Utility.Wait(0.05)
endWhile
else
Debug.MessageBox("Failed to load shop merchandise. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
endif
endif
EndEvent

View File

@ -0,0 +1,28 @@
scriptname BRMerchToggleScript extends ObjectReference
Keyword property BRLinkMerchShelf auto
Keyword property BRLinkMerchChest auto
Keyword property BRLinkItemRef auto
Keyword property BRLinkMerchToggle auto
Keyword property BRLinkMerchNext auto
Keyword property BRLinkMerchPrev auto
Activator property PlaceholderStatic auto
Actor property PlayerRef auto
Quest Property BRQuest Auto
Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerRef
ObjectReference MerchantShelf = self.GetLinkedRef(BRLinkMerchShelf)
BRQuestScript BRScript = BRQuest as BRQuestScript
bool result = BRMerchandiseList.Toggle(BRScript.ApiUrl, BRScript.ApiKey, BRScript.MerchandiseListId, MerchantShelf, PlaceholderStatic, BRLinkMerchShelf, BRLinkMerchChest, BRLinkItemRef, BRLinkMerchToggle, BRLinkMerchNext, BRLinkMerchPrev)
debug.Trace("BRMerchandiseList.Toggle result: " + result)
if result
while !BRMerchandiseList.Replace3D(MerchantShelf, PlaceholderStatic, BRLinkMerchShelf, BRLinkItemRef)
Debug.Trace("BRMerchandiseList.Replace3D returned false, waiting and trying again")
Utility.Wait(0.05)
endWhile
else
Debug.MessageBox("Failed to load or clear shop merchandise. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
endif
endif
EndEvent

View File

@ -0,0 +1,12 @@
scriptname BRMerchandiseList
; TODO: a save function that saves the merch to the server, load should load from server
bool function Toggle(string apiUrl, string apiKey, int merchandise_list_id, ObjectReference merchantShelf, Form placeholderStatic, Keyword shelfKeyword, Keyword chestKeyword, Keyword itemKeyword, Keyword toggleKeyword, Keyword nextKeyword, Keyword prevKeyword) global native
bool function NextPage(string apiUrl, string apiKey, int merchandise_list_id, ObjectReference merchantShelf, Form placeholderStatic, Keyword shelfKeyword, Keyword chestKeyword, Keyword itemKeyword, Keyword toggleKeyword, Keyword nextKeyword, Keyword prevKeyword) global native
bool function PrevPage(string apiUrl, string apiKey, int merchandise_list_id, ObjectReference merchantShelf, Form placeholderStatic, Keyword shelfKeyword, Keyword chestKeyword, Keyword itemKeyword, Keyword toggleKeyword, Keyword nextKeyword, Keyword prevKeyword) global native
bool function Replace3D(ObjectReference merchantShelf, Form placeholderStatic, Keyword shelfKeyword, Keyword itemKeyword) global native
Form function Buy(ObjectReference merchandisePlaceholder) global native
int function Create(string apiUrl, string apiKey, int shopId, ObjectReference merchantChest) global native

View File

@ -0,0 +1,3 @@
scriptname BROwner
int function Create(string apiUrl, string apiKey, string name, int modVersion) global native

View File

@ -0,0 +1,19 @@
Scriptname BRQuestPlayerAliasScript extends ReferenceAlias
Cell property BREmpty auto
event OnPlayerLoadGame()
Debug.Trace("Player load game")
Cell currentCell = self.GetReference().GetParentCell()
if currentCell == BREmpty
Debug.Trace("Player's loaded cell is BREmpty, resetting merch")
endif
endEvent
event OnCellLoad()
Debug.Trace("Player load cell")
Cell currentCell = self.GetReference().GetParentCell()
if currentCell == BREmpty
Debug.Trace("Player's loaded cell is BREmpty, resetting merch")
endif
endEvent

View File

@ -0,0 +1,143 @@
scriptname BRQuestScript extends Quest
int property ModVersion = 1 auto
string property ApiUrl = "https://api.bazaarrealm.com" auto
string property ApiKey auto
actor property PlayerRef auto
int property OwnerId auto
; TODO: need to be able to create multiple shops
int property ShopId auto
; TODO: loop up interior refs by shop id instead of saving this
int property InteriorRefListId = 29 auto ; TODO: temp fixing to id 20
int property MerchandiseListId = 2 auto ; TODO: temp fixing to id 2
ObjectReference property ShopXMarker auto
UILIB_1 property UILib auto
int function GetVersion()
return 1
endFunction
event OnInit()
Debug.Trace("BRQuestScript OnInit")
Maintenance()
endEvent
function Maintenance()
Debug.Trace("BRQuestScript Maintenance")
UILib = (Self as Form) as UILIB_1
BRClient.Init()
int newVersion = GetVersion()
if ModVersion < newVersion
ModVersion = newVersion
; TODO: update tasks
Debug.Notification("Bazaar Realm upgraded to version: " + ModVersion)
endif
endFunction
bool function StartMod()
debug.Trace("BRQuestScript StartMod")
bool result = BRClient.StatusCheck(ApiUrl)
if result
ApiKey = BRClient.GenerateApiKey()
Debug.Trace("apiKey: " + ApiKey)
Debug.Trace("apiUrl: " + ApiUrl)
string playerName = Game.GetPlayer().GetBaseObject().GetName()
OwnerId = BROwner.Create(ApiUrl, ApiKey, playerName, ModVersion)
if OwnerId > -1
ShopId = BRShop.Create(ApiUrl, ApiKey, playerName + "'s Shop")
if ShopId > -1
Debug.Notification("Initialized Bazaar Realm client")
else
result = false
Debug.MessageBox("Failed to initialize Bazaar Realm client. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
endif
else
result = false
Debug.MessageBox("Failed to initialize Bazaar Realm client. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
endif
else
Debug.MessageBox("Failed to initialize Bazaar Realm client. The API server might be down: " + ApiUrl)
endif
return result
endFunction
bool function SaveInteriorRefs()
; TODO: this should not save anything if player is not currently in their shop
Cell currentCell = PlayerRef.GetParentCell()
InteriorRefListId = BRInteriorRefList.Create(ApiUrl, ApiKey, ShopId, currentCell)
Debug.Trace("Interior ref list id: " + interiorRefListId)
; Int numRefs = currentCell.GetNumRefs()
; debug.Trace("Num of refs in current cell: " + numRefs)
; Int refIndex = 0
; while refIndex <= numRefs
; ObjectReference ref = currentCell.GetNthRef(refIndex)
; ; if ref != None && ref.IsEnabled()
; ; Form a_form = ref.GetBaseObject()
; ; debug.Trace("Ref " + refIndex + ": " + ref.GetDisplayName())
; ; debug.Trace("Ref position: " + ref.X + ", " + ref.Y + ", " + ref.Z)
; ; debug.Trace("Ref angle: " + ref.getAngleX() + ", " + ref.getAngleY() + ", " + ref.getAngleZ())
; ; debug.Trace("Ref scale: " + ref.GetScale())
; ; debug.Trace("Ref Base Object Name: " + a_form.GetName() + " (" + a_form.GetType() + ")")
; ; Int formId = a_form.GetFormID()
; ; if (formId < 0)
; ; ; GetFormId is broken for light mods, so we have to fix this ourselves
; ; formId = formId + 2147483647 ; formId + INT_MAX
; ; debug.Trace("Ref (light) form id: " + formId)
; ; Int localFormId = Math.LogicalAnd(formId, 4095) + 1 ; (formId & 0xfff) + 1
; ; debug.Trace("Ref (light) local form id: " + localFormId)
; ; Int modIndex = Math.LogicalAnd(Math.RightShift(formId, 12), 4095) ; (formId >> 12) & 0xfff
; ; debug.Trace("Light mod index: " + modIndex)
; ; String modName = Game.GetLightModName(modIndex)
; ; debug.Trace("Light mod name: " + modName)
; ; else
; ; debug.Trace("Ref form id: " + formId)
; ; Int localFormId = Math.LogicalAnd(formId, 16777215); formId & 0xffffff
; ; debug.Trace("Ref local form id: " + localFormId)
; ; Int modIndex = Math.RightShift(formId, 24)
; ; debug.Trace("Mod index: " + modIndex)
; ; String modName = Game.GetModName(modIndex)
; ; debug.Trace("Mod name: " + modName)
; ; endIf
; ; endIf
; debug.Trace("Ref " + refIndex)
; refIndex += 1
; endWhile
debug.Trace("Done looping through refs")
if InteriorRefListId > -1
return true
else
Debug.MessageBox("Failed to save shop. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
return false
endif
endFunction
bool function LoadInteriorRefs()
; TODO: this should not save anything if player is not currently in their shop
Cell currentCell = PlayerRef.GetParentCell()
bool result = BRInteriorRefList.ClearCell(currentCell)
debug.Trace("ClearCell result: " + result)
result = BRInteriorRefList.Load(ApiUrl, ApiKey, InteriorRefListId, currentCell, ShopXMarker)
debug.Trace("Done loading interior refs from API")
if result
return true
else
Debug.MessageBox("Failed to load shop. Please submit a bug on Nexus Mods with the contents of BazaarRealmPlugin.log and BazaarRealmClient.log usually located in C:\\Users\\<your user>\\Documents\\My Games\\Skyrim Special Edition\\SKSE.")
return false
endif
endFunction
int function ListMerchandise()
string[] options = new string[5]
options[0] = "First Item"
options[1] = "Second Item"
options[2] = "Third Item"
options[3] = "Fourth Item"
options[4] = "Fifth Item"
int selectedIndex = UILib.ShowList("Shop Merchandise", options, 0, 0)
UILib.ShowNotification("Chose " + options[selectedIndex], "#74C56D")
endFunction
bool function LoadMerchandise()
Debug.MessageBox("This no longer does anything, sorry.")
endFunction

View File

@ -0,0 +1,3 @@
scriptname BRShop
int function Create(string apiUrl, string apiKey, string name, string description = "") global native

View File

@ -0,0 +1,12 @@
Scriptname CMFetchPlayerAliasScript extends ReferenceAlias
CMFetchThreadManager Property ThreadManagerScript Auto
event OnPlayerLoadGame()
debug.Trace("CMFetchPlayerAliasScript OnPlayerLoadGame")
MyClass.Init()
ThreadManagerScript.Init()
String uuid = MyClass.CreateUuid()
debug.Trace("uuid: " + uuid)
debug.Notification("Your uuid: " + uuid)
endEvent

View File

@ -0,0 +1,37 @@
Scriptname CMFetchThread extends Quest hidden
Bool threadQueued = false
String function GetAsync()
threadQueued = true
endFunction
Bool function IsQueued()
return threadQueued
endFunction
Bool function ForceUnlock()
threadQueued = false
return true
endFunction
Event OnFetch()
debug.Trace("CMFetchThread OnFetch")
if threadQueued
String helloWorld = MyClass.HelloWorld()
debug.Trace("helloWorld: " + helloWorld)
RaiseEvent_FetchReturnedCallback(helloWorld)
threadQueued = false
endif
endEvent
function RaiseEvent_FetchReturnedCallback(String response)
debug.Trace("CMFetchThread RaiseEvent_FetchReturnedCallback")
int handle = ModEvent.Create("Shopkeeping_FetchReturnedCallback")
if handle
ModEvent.PushString(handle, response)
ModEvent.Send(handle)
else
;pass
endif
endFunction

View File

@ -0,0 +1 @@
Scriptname CMFetchThread01 extends CMFetchThread

View File

@ -0,0 +1,72 @@
Scriptname CMFetchThreadManager extends Quest
Quest Property CMFetchQuest Auto
CMFetchThread01 thread01
Event OnInit()
debug.Trace("CMFetchThreadManager OnInit")
;Init()
endEvent
function Init()
debug.Trace("CMFetchThreadManager Init")
RegisterForModEvent("Shopkeeping_OnFetch", "OnFetch")
RegisterForModEvent("Shopkeeping_FetchReturnedCallback", "FetchReturnedCallback")
thread01 = CMFetchQuest as CMFetchThread01
debug.Trace("CMFetchThreadManager starting fetch async")
FetchAsync()
WaitAll()
endFunction
function FetchAsync()
debug.Trace("CMFetchThreadManager FetchAsync")
if !thread01.IsQueued()
thread01.GetAsync()
else
debug.Trace("CMFetchThreadManager FetchAsync thread already queued!")
WaitAll()
FetchAsync()
endif
endFunction
function WaitAll()
RaiseEvent_OnFetch()
BeginWaiting()
endFunction
function BeginWaiting()
Bool waiting = true
Int i = 0
while waiting
if thread01.IsQueued()
i += 1
Utility.wait(0.1)
if i >= 100
debug.trace("Error: A catastrophic error has occurred. All threads have become unresponsive. Please debug this issue or notify the author.")
i = 0
;Fail by returning None. The mod needs to be fixed.
return
endif
else
waiting = false
endif
endWhile
endFunction
function RaiseEvent_OnFetch()
Int handle = ModEvent.Create("Shopkeeping_OnFetch")
if handle
ModEvent.Send(handle)
else
;pass
endif
endFunction
Event FetchReturnedCallback(String response)
debug.Trace("FetchReturnedCallback: " + response)
debug.Notification(response)
debug.MessageBox(response)
endEvent

View File

@ -0,0 +1,14 @@
Scriptname CMPeddlingChestScript extends Form
Quest Property CMPeddling Auto
event OnMenuClose(string menuName)
if menuName == "ContainerMenu"
debug.Trace("Peddling container menu closed")
CMPeddlingScript questScript = CMPeddling as CMPeddlingScript
debug.Trace("CMPeddling: " + CMPeddling)
debug.Trace("questScript: " + questScript)
questScript.ReweighPeddlingInventory()
UnregisterForMenu("ContainerMenu")
endif
endEvent

View File

@ -0,0 +1,21 @@
Scriptname CMPeddlingInventoryChestScript extends ObjectReference
Actor Property PlayerRef Auto
ObjectReference Property CMPeddlingChestRef Auto
Armor Property CMPeddlingInventory Auto
Container Property CMPeddlingChest Auto
Quest Property CMFetchQuest Auto
Event OnEquipped(Actor akActor)
if akActor == PlayerRef
Game.DisablePlayerControls(False, False, False, False, False, True)
PlayerRef.EquipItem(CMPeddlingInventory, True, True)
Utility.Wait(0.01)
PlayerRef.UnequipItem(CMPeddlingInventory, False, True)
Game.EnablePlayerControls(False, False, False, False, False, True)
debug.Trace("CMPeddlingChest: " + CMPeddlingChest as Form)
CMPeddlingChest.RegisterForMenu("ContainerMenu")
CMPeddlingChestRef.Activate(akActor)
endif
endEvent

View File

@ -0,0 +1,8 @@
Scriptname CMPeddlingPlayerAliasScript extends ReferenceAlias
CMPeddlingScript Property QuestScript Auto
event OnPlayerLoadGame()
debug.Trace("CMPeddlingPlayerAliasScript OnPlayerLoadGame")
QuestScript.Maintenance()
endEvent

View File

@ -0,0 +1,721 @@
Scriptname CMPeddlingScript extends Quest
import Math
Message Property CMPeddlingHaggleStart Auto
Message Property CMPeddlingHaggleStartAdjust Auto
Message Property CMPeddlingHaggleCounter Auto
Message Property CMPeddlingHaggleCounterStart Auto
Message Property CMPeddlingHaggleCountChange Auto
Actor Property PlayerRef Auto
ObjectReference Property CMPeddlingChestRef Auto
Armor Property CMPeddlingInventory Auto
MiscObject Property Gold001 Auto
Keyword Property ClothingRich Auto
Keyword Property ClothingPoor Auto
Keyword Property JewelryExpensive Auto
Faction Property JobMerchantFaction Auto
Faction Property JobHostlerFaction Auto
Faction Property KhajiitCaravanFaction Auto
Faction Property JobInnkeeperFaction Auto
Faction Property JobBardFaction Auto
Faction Property JobFarmerFaction Auto
Faction Property JobMinerFaction Auto
Faction Property JobPriestFaction Auto
Faction Property JobCarriageFaction Auto
Faction Property JobFenceFaction Auto
Faction Property JobJarlFaction Auto
Faction Property JobStewardFaction Auto
Faction Property JobHousecarlFaction Auto
Faction Property JobCourtWizardFaction Auto
Faction Property FavorJobsBeggarsFaction Auto
Faction Property FavorJobsDrunksFaction Auto
Faction Property GuardDialogueFaction Auto
Float version
event OnInit()
debug.Trace("CMPeddlingScript OnInit")
MyClass.Init()
String uuid = MyClass.CreateUuid()
debug.Trace("uuid: " + uuid)
debug.Notification("Your uuid: " + uuid)
Maintenance()
endEvent
function Maintenance()
debug.Trace("CMPeddlingScript Maintenance!")
if version < 0.01
version = 0.01
debug.Notification("Now running Shopkeeper version: " + version)
endif
ReweighPeddlingInventory()
endFunction
function ReweighPeddlingInventory()
Float totalWeight = 0
Int formIndex = CMPeddlingChestRef.GetNumItems()
debug.Trace("Merchandise has " + formIndex + " items, reweighing...")
while formIndex > 0
formIndex -= 1
Form nthForm = CMPeddlingChestRef.GetNthForm(formIndex)
Int numOfForm = CMPeddlingChestRef.GetItemCount(nthForm)
totalWeight += nthForm.GetWeight() * numOfForm
; Serialize testing
Int formId = nthForm.GetFormID()
if (formId < 0)
; GetFormId is broken for light mods, so we have to fix this ourselves
formId = formId + 2147483647 ; formId + INT_MAX
debug.Trace("Thing (light) form id: " + formId)
Int localFormId = Math.LogicalAnd(formId, 4095) + 1 ; (formId & 0xfff) + 1
debug.Trace("Thing (light) local form id: " + localFormId)
Int modIndex = Math.LogicalAnd(Math.RightShift(formId, 12), 4095) ; (formId >> 12) & 0xfff
debug.Trace("Light mod index: " + modIndex)
String modName = Game.GetLightModName(modIndex)
debug.Trace("Light mod name: " + modName)
else
debug.Trace("Thing form id: " + formId)
Int localFormId = Math.LogicalAnd(formId, 16777215); formId & 0xffffff
debug.Trace("Thing (light) local form id: " + localFormId)
Int modIndex = Math.RightShift(formId, 24)
debug.Trace("Mod index: " + modIndex)
String modName = Game.GetModName(modIndex)
debug.Trace("Mod name: " + modName)
endIf
endWhile
debug.Trace("Setting merchandise weight to " + totalWeight)
CMPeddlingInventory.SetWeight(totalWeight)
; Deserialize test
if CMPeddlingChestRef.GetNumItems() != 0
debug.Trace("CMPeddlingScript chest empty")
Bool isLightMod = True
String modName = "Dovah Nord Weapons.esp"
Int localFormId = 2053
Form formToAdd = Game.GetFormFromFile(localFormId, modName)
debug.Trace("Adding form to chest: " + formToAdd)
CmPeddlingChestRef.AddItem(formToAdd, 1)
isLightMod = True
modName = "Dunmeri Leaf Sword.esp"
localFormId = 2048
formToAdd = Game.GetFormFromFile(localFormId, modName)
debug.Trace("Adding form to chest: " + formToAdd)
CmPeddlingChestRef.AddItem(formToAdd, 1)
isLightMod = False
modName = "Evening Star.esp"
localFormId = 3426
formToAdd = Game.GetFormFromFile(localFormId, modName)
debug.Trace("Adding form to chest: " + formToAdd)
CmPeddlingChestRef.AddItem(formToAdd, 1)
endIf
debug.Trace("Dunmeri Leaf Sword.esp: " + Game.GetModByName("Dunmeri Leaf Sword.esp"))
debug.Trace("Evening Star.esp: " + Game.GetModByName("Evening Star.esp"))
debug.Trace("Dovah Nord Weapons.esp: " + Game.GetModByName("Dovah Nord Weapons.esp"))
; Test spawning user placed references
Form candlestickForm = Game.GetFormEx(934623)
ObjectReference candlestickRef = PlayerRef.PlaceAtMe(candlestickForm, 1, false, true)
candlestickRef.SetPosition(-62.375675, -437.171265, 78.617851)
candlestickRef.SetAngle(93.194153, 42.144417, -109.048126)
candlestickRef.SetScale(1.0)
candleStickRef.Enable()
; Test scanning and serializing reference positions
Cell currentCell = PlayerRef.GetParentCell()
Int numRefs = currentCell.GetNumRefs()
debug.Trace("Num of refs in current cell: " + numRefs)
Int refIndex = 0
while refIndex <= numRefs
ObjectReference ref = currentCell.GetNthRef(refIndex)
if ref != None
debug.Trace("Ref " + refIndex + ": " + ref.GetBaseObject().GetType())
debug.Trace("Ref " + refIndex + ": " + ref.GetBaseObject().GetName())
endIf
if ref != None && ref.GetDisplayName() == "Candlestick"
debug.Trace("Ref " + refIndex + ": " + ref.GetDisplayName())
debug.Trace("Ref position: " + ref.X + ", " + ref.Y + ", " + ref.Z)
debug.Trace("Ref angle: " + ref.getAngleX() + ", " + ref.getAngleY() + ", " + ref.getAngleZ())
debug.Trace("Ref scale: " + ref.GetScale())
debug.Trace("Ref enabled: " + ref.IsEnabled())
debug.Trace("Ref Base Object Name: " + ref.GetBaseObject().GetName() + " (" + ref.GetBaseObject().GetType() + ")")
endIf
refIndex += 1
endWhile
debug.Trace("Done looping through refs")
endFunction
function Peddle(Actor buyer)
Int buyerWealth = GetNPCWealth(buyer)
debug.Trace("Buyer wealth: " + buyerWealth)
Int totalItems = CMPeddlingChestRef.GetNumItems()
String buyerName = buyer.GetBaseObject().GetName()
debug.Trace("Chest total items " + totalItems)
debug.Trace("Buyer: " + buyer)
debug.Trace("Buyer BaseObject: " + buyer.GetBaseObject())
debug.Trace("Buyer Name: " + buyer.GetBaseObject().GetName())
debug.Trace("Buyer gold: " + buyer.GetItemCount(Gold001))
Float buyerSpeech = buyer.GetAV("Speechcraft")
debug.Trace("Buyer speechcraft: " + buyerSpeech)
Float playerSpeech = PlayerRef.GetAV("Speechcraft")
debug.Trace("Player speechcraft: " + playerSpeech)
if totalItems > 0
Int randomItemIndex = Utility.RandomInt(0, totalItems - 1)
Form formToSell = CMPeddlingChestRef.GetNthForm(randomItemIndex)
debug.Trace("formToSell" + formToSell + " " + formToSell.GetName())
Int numOfForm = CMPeddlingChestRef.GetItemCount(formToSell)
debug.Trace("Chest has " + numOfForm)
Int numOfFormToSell = Utility.RandomInt(1, numOfForm)
debug.Trace("Selling " + numOfFormToSell)
Int formPrice = GetFormGoldValue(formToSell)
Int formTotal = formPrice * numOfFormToSell
debug.Trace("For gold: " + formTotal)
String formName = formToSell.GetName()
debug.Notification(buyerName + " wants to buy " + numOfFormToSell + " " + \
formName + "(s).")
Int[] playerDecision = HaggleMenu(numOfFormToSell, formPrice, formTotal, formName, buyerName)
Int outcome = playerDecision[0]
Int bidPrice = playerDecision[1]
Int offerPrice = playerDecision[1]
Int haggleNumOfForm = numOfFormToSell
Int[] buyerDecision
while outcome
buyerDecision = BuyerAcceptRejectOrCounter(buyerWealth, buyerSpeech, playerSpeech, formToSell, \
numOfFormToSell, numOfForm, formPrice, bidPrice)
outcome = buyerDecision[0]
haggleNumOfForm = buyerDecision[1]
bidPrice = buyerDecision[2]
if buyerDecision[0] == 0 ; Buyer Reject
elseif buyerDecision[0] == 1 ; Buyer Accept
Int haggleGold = numOfFormToSell * bidPrice
CMPeddlingChestRef.RemoveItem(formToSell, numOfFormToSell)
buyer.AddItem(formToSell, numOfFormToSell)
PlayerRef.AddItem(Gold001, haggleGold)
ReweighPeddlingInventory()
debug.Notification(numOfFormToSell + " " + formName + "(s) removed from Merchandise")
return
elseif buyerDecision[0] == 2 ; Buyer Counterbid
playerDecision = HaggleMenuCounter(haggleNumOfForm, formPrice, formTotal, bidPrice, offerPrice, \
formName, buyerName)
outcome = playerDecision[0]
bidPrice = playerDecision[1]
elseif buyerDecision[0] == 3 ; Buyer Counter num
Int haggleFormTotal = formPrice * haggleNumOfForm
Bool playerChoice = HaggleMenuCountChange(numOfFormToSell, haggleNumOfForm, formPrice, \
haggleFormTotal, bidPrice, formName, buyerName)
if playerChoice ; Player Accept
Int haggleGold = haggleNumOfForm * bidPrice
CMPeddlingChestRef.RemoveItem(formToSell, haggleNumOfForm)
buyer.AddItem(formToSell, haggleNumOfForm)
PlayerRef.AddItem(Gold001, haggleGold)
ReweighPeddlingInventory()
debug.Notification(haggleNumOfForm + " " + formName + "(s) removed from Merchandise")
else ; Player Reject
outcome = 0
endif
endif
endWhile
debug.Notification("Trade rejected.")
else
debug.Notification("You have no merchandise to sell.")
endif
endFunction
Int[] function HaggleMenu(Int numOfFormToSell, Int formPrice, Int formTotal, String formName, String buyerName)
Int haggleDelta = 0
Int hagglePrice = formPrice + haggleDelta
Int haggleTotal = hagglePrice * numOfFormToSell
Int profitGold = haggleTotal - formTotal
Float profitPercent = GetProfitPercent(profitGold, formTotal)
Bool menuOpen = true
Int[] decision = new Int[2]
Int buttonPressed = 8
while buttonPressed == 8
buttonPressed = CMPeddlingHaggleStart.Show(numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
if buttonPressed == 8
debug.Notification(buyerName + " wants to buy " + numOfFormToSell + " " + \
formName + "(s).")
endif
endWhile
while menuOpen
if buttonPressed == -1
elseif buttonPressed == 0
menuOpen = false
decision[0] = 0
decision[1] = hagglePrice
return decision
elseif buttonPressed == 1
haggleDelta -= 100
hagglePrice = formPrice + haggleDelta
if hagglePrice < 0
haggleDelta -= hagglePrice
hagglePrice = 0
endif
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 2
haggleDelta -= 10
hagglePrice = formPrice + haggleDelta
if hagglePrice < 0
haggleDelta -= hagglePrice
hagglePrice = 0
endif
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 3
haggleDelta -= 1
hagglePrice = formPrice + haggleDelta
if hagglePrice < 0
haggleDelta -= hagglePrice
hagglePrice = 0
endif
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 4
; TODO: Auto Haggle
menuOpen = false
decision[0] = 0
decision[1] = hagglePrice
return decision
elseif buttonPressed == 5
haggleDelta += 1
hagglePrice = formPrice + haggleDelta
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 6
haggleDelta += 10
hagglePrice = formPrice + haggleDelta
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 7
haggleDelta += 100
hagglePrice = formPrice + haggleDelta
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 8
debug.Notification(buyerName + " wants to buy " + numOfFormToSell + " " + \
formName + "(s).")
buttonPressed = CMPeddlingHaggleStartAdjust.Show(haggleDelta, numOfFormToSell, formPrice, hagglePrice, \
haggleTotal, profitPercent, profitGold)
elseif buttonPressed == 9
menuOpen = false
decision[0] = 1
decision[1] = hagglePrice
return decision
endif
endWhile
endFunction
Int[] function HaggleMenuCounter(Int numOfFormToSell, Int formPrice, Int formTotal, Int buyerPrice, \
Int offerPrice, String formName, String buyerName)
Int buyerTotal = buyerPrice * numOfFormToSell
Int haggleDelta = 0
Int hagglePrice = buyerPrice + haggleDelta
Int haggleTotal = hagglePrice * numOfFormToSell
Int profitGold = haggleTotal - formTotal
Float profitPercent = GetProfitPercent(profitGold, formTotal)
Int offerTotal = offerPrice * numOfFormToSell
Int buyerDelta = buyerPrice - offerPrice
Bool menuOpen = true
Int[] decision = new Int[2]
Int buttonPressed = 8
while buttonPressed == 8
buttonPressed = CMPeddlingHaggleCounterStart.Show(buyerDelta, numOfFormToSell, formPrice, offerPrice, \
offerTotal, hagglePrice, buyerTotal, profitPercent, \
profitGold)
if buttonPressed == 8
debug.Notification(buyerName + " wants to buy " + numOfFormToSell + " " + \
formName + "(s).")
endif
endWhile
while menuOpen
if buttonPressed == -1
elseif buttonPressed == 0
menuOpen = false
decision[0] = 0
decision[1] = hagglePrice
return decision
elseif buttonPressed == 1
haggleDelta -= 100
hagglePrice = buyerPrice + haggleDelta
if hagglePrice < 0
haggleDelta -= hagglePrice
hagglePrice = 0
endif
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 2
haggleDelta -= 10
hagglePrice = buyerPrice + haggleDelta
if hagglePrice < 0
haggleDelta -= hagglePrice
hagglePrice = 0
endif
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 3
haggleDelta -= 1
hagglePrice = buyerPrice + haggleDelta
if hagglePrice < 0
haggleDelta -= hagglePrice
hagglePrice = 0
endif
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 4
; TODO: Auto Haggle
menuOpen = false
decision[0] = 0
decision[1] = hagglePrice
elseif buttonPressed == 5
haggleDelta += 1
hagglePrice = buyerPrice + haggleDelta
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 6
haggleDelta += 10
hagglePrice = buyerPrice + haggleDelta
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 7
haggleDelta += 100
hagglePrice = buyerPrice + haggleDelta
haggleTotal = hagglePrice * numOfFormToSell
profitGold = haggleTotal - formTotal
profitPercent = GetProfitPercent(profitGold, formTotal)
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 8
debug.Notification(buyerName + " wants to buy " + numOfFormToSell + " " + \
formName + "(s).")
buttonPressed = CMPeddlingHaggleCounter.Show(haggleDelta, numOfFormToSell, formPrice, buyerPrice, \
buyerTotal, hagglePrice, haggleTotal, profitPercent, \
profitGold)
elseif buttonPressed == 9
menuOpen = false
decision[0] = 1
decision[1] = hagglePrice
return decision
endif
endWhile
endFunction
Bool function HaggleMenuCountChange(Int numOfFormToSell, Int haggleNumOfForm, Int formPrice, Int formTotal, \
Int bidPrice, String formName, String buyerName)
Int haggleGold = haggleNumOfForm * bidPrice
Int profitGold = haggleGold - formTotal
Float profitPercent = GetProfitPercent(profitGold, formTotal)
Int buyerItemCountDelta = haggleNumOfForm - numOfFormToSell
Bool menuOpen = true
Int buttonPressed = 8
while buttonPressed == 8
buttonPressed = CMPeddlingHaggleCountChange.Show(buyerItemCountDelta, haggleNumOfForm, formPrice, \
bidPrice, haggleGold, profitPercent, profitGold)
if buttonPressed == 8
debug.Notification(buyerName + " wants to buy " + haggleNumOfForm + " " + \
formName + "(s).")
endif
endWhile
while menuOpen
if buttonPressed == 0 ; Player Reject
menuOpen = false
return false
elseif buttonPressed == 1
debug.Notification(buyerName + " wants to buy " + numOfFormToSell + " " + \
formName + "(s).")
buttonPressed = CMPeddlingHaggleCountChange.Show(buyerItemCountDelta, haggleNumOfForm, formPrice, \
bidPrice, haggleGold, profitPercent, profitGold)
elseif buttonPressed == 2 ; Player Accept
menuOpen = false
return true
endif
endWhile
endFunction
Int[] function BuyerAcceptRejectOrCounter(Int buyerWealth, Float buyerSpeech, Float playerSpeech, Form formToBuy, \
Int numOfFormToBuy, Int numOfFormAvailable, Int formPrice, Int bidPrice)
Int[] decisionValues = new Int[3]
Int decision = Utility.RandomInt(0, 3)
Float speechDelta = buyerSpeech - playerSpeech
debug.Trace("speechDelta: " + priceToWealthRatio)
Int haggleDelta = bidPrice - formPrice
debug.Trace("haggleDelta: " + priceToWealthRatio)
Int totalPrice = bidPrice * numOfFormToBuy
debug.Trace("totalPrice: " + priceToWealthRatio)
Float priceToWealthRatio = totalPrice / buyerWealth
debug.Trace("priceToWealthRatio: " + priceToWealthRatio)
Float haggleToPriceRatio = haggleDelta / formPrice
debug.Trace("haggleToPriceRatio: " + haggleToPriceRatio)
Float speechRatio = speechDelta / playerSpeech
debug.Trace("speechRatio: " + haggleToPriceRatio)
Float priceFairness = haggleToPriceRatio + speechRatio
debug.Trace("priceFairness: " + priceFairness)
if priceFairness < 0
; Good price
if priceToWealthRatio < 0.5 && (numOfFormToBuy < numOfFormAvailable)
; Stock up, increase count
Int countMax = ((0.75 * buyerWealth) / bidPrice) as Int
if countMax < 1
; Reject
decisionValues[0] = 0
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
endif
; Because Math.min is not a thing aparently??
Int max = countMax
if numOfFormAvailable > countMax
max = numOfFormAvailable
endif
Int newCount = Utility.RandomInt(numOfFormToBuy, max)
decisionValues[0] = 3
decisionValues[1] = newCount
decisionValues[2] = bidPrice
return decisionValues
elseif priceToWealthRatio > 0.75
if numOfFormToBuy > 1
; Decrease count
Int countMax = (0.75 * buyerWealth) as Int / bidPrice as Int
if countMax < 1
; Reject
decisionValues[0] = 0
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
endif
Int newCount = Utility.RandomInt(1, countMax)
decisionValues[0] = 3
decisionValues[1] = newCount
decisionValues[2] = bidPrice
return decisionValues
else
; Reject
decisionValues[0] = 0
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
endif
endif
elseif priceFairness > 2.0
; price too absurd
; Reject
decisionValues[0] = 0
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
elseif priceFairness > 0.2
; Price unfair
; Counter
Int newBid = ((0.2 - speechRatio) * formPrice) as Int + formPrice as Int
decisionValues[0] = decision
decisionValues[1] = numOfFormToBuy
decisionValues[2] = newBid
return decisionValues
else
; Price fair
if priceToWealthRatio > 0.5
if numOfFormToBuy > 1
; Decrease count
Int countMax = (0.5 * buyerWealth) as Int / bidPrice as Int
Int newCount = Utility.RandomInt(0, countMax)
if newCount > 0
decisionValues[0] = 3
decisionValues[1] = newCount
decisionValues[2] = bidPrice
return decisionValues
else
; Reject
decisionValues[0] = 0
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
endif
else
; Reject
decisionValues[0] = 0
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
endif
endif
endif
; Accept
decisionValues[0] = 1
decisionValues[1] = numOfFormToBuy
decisionValues[2] = bidPrice
return decisionValues
endFunction
; Thanks to Puff The Magic Dragon for the idea for this calculation from their breezehome store mod:
; https://www.nexusmods.com/skyrim/mods/60466/
; https://forums.nexusmods.com/index.php?/topic/2323334-getgoldvalue-on-enchantedupgraded-items/?p=20447629
Int function GetFormGoldValue(Form theForm)
Armor anArmor = theForm as Armor
Weapon aWeapon = theForm as Weapon
Enchantment ench
Int enchValue = 0
Int charge = 0
Int goldValue = theForm.GetGoldValue()
if anArmor || aWeapon
ObjectReference droppedItem = CMPeddlingChestRef.dropObject(theForm, 1)
CMPeddlingChestRef.AddItem(theForm, 1)
goldValue = droppedItem.GetGoldValue()
if anArmor
ench = anArmor.GetEnchantment()
enchValue = ench.GetGoldValue()
elseif aWeapon
ench = aWeapon.GetEnchantment()
charge = droppedItem.GetItemCharge() as Int
enchValue = (ench.GetGoldValue() * 8) + (charge * 0.12) as Int
endif
droppedItem.Delete()
droppedItem = None
goldValue += enchValue
endif
return goldValue
; Alternative calculation that doesn't work :(
; if ench
; Int index = 0
; while index < ench.GetNumEffects()
; MagicEffect effect = ench.GetNthEffectMagicEffect(index)
; Float effectBaseCost = effect.GetBaseCost()
; Float mag = ench.GetNthEffectMagnitude(index)
; Int dur = ench.GetNthEffectDuration(index)
; goldValue = goldValue + ( (effectBaseCost * 8) * (Math.pow(mag, 1.1)) * (Math.pow(dur / 10, 1.1)) ) as Int
; index += 1
; endWhile
; endif
endFunction
Float function GetProfitPercent(Int profitGold, Int formTotal)
Float profitPercent
if formTotal == 0
profitPercent = profitGold * 100 as Float
else
profitPercent = (profitGold as Float / formTotal as Float) * 100
endif
return profitPercent
endFunction
Int function GetNPCWealth(Actor npc)
Int wealth = 0
wealth += npc.GetGoldAmount()
wealth += npc.GetBribeAmount()
Int level = npc.GetLevel()
wealth += Utility.RandomInt(level, level * 4)
if npc.IsInFaction(JobJarlFaction)
wealth += 700
elseif npc.IsInFaction(JobStewardFaction)
wealth += 600
elseif npc.IsInFaction(JobHousecarlFaction)
wealth += 550
elseif npc.IsInFaction(JobCourtWizardFaction)
wealth += 550
elseif npc.IsInFaction(JobMerchantFaction)
wealth += 500
elseif npc.IsInFaction(JobHostlerFaction)
wealth += 400
elseif npc.IsInFaction(JobFenceFaction)
wealth += 350
elseif npc.IsInFaction(KhajiitCaravanFaction)
wealth += 300
elseif npc.IsInFaction(JobInnkeeperFaction)
wealth += 300
elseif npc.IsInFaction(JobCarriageFaction)
wealth += 250
elseif npc.IsInFaction(JobBardFaction)
wealth += 200
elseif npc.IsInFaction(GuardDialogueFaction)
wealth += 200
elseif npc.IsInFaction(JobFarmerFaction)
wealth += 100
elseif npc.IsInFaction(JobMinerFaction)
wealth += 100
elseif npc.IsInFaction(JobPriestFaction)
wealth += 100
elseif npc.IsInFaction(FavorJobsBeggarsFaction)
wealth -= 100
elseif npc.IsInFaction(FavorJobsDrunksFaction)
wealth -= 100
endif
Int totalItemValue = 0
Int formIndex = npc.GetNumItems()
while formIndex > 0
formIndex -= 1
Form nthForm = npc.GetNthForm(formIndex)
Int numOfForm = npc.GetItemCount(nthForm)
totalItemValue += nthForm.GetGoldValue() * numOfForm
endWhile
wealth += totalItemValue
if npc.WornHasKeyword(ClothingRich)
wealth += 100
endif
if npc.WornHasKeyword(ClothingPoor)
wealth -= 100
endif
if npc.WornHasKeyword(JewelryExpensive)
wealth += 100
endif
if wealth < 0
wealth = Utility.RandomInt(0, 25)
endif
return wealth
endFunction

19
skyrimse.ppj Normal file
View File

@ -0,0 +1,19 @@
<?xml version='1.0'?><!-- Game is either sse, tesv, or fo4 -->
<PapyrusProject xmlns="PapyrusProject.xsd"
Flags="TESV_Papyrus_Flags.flg"
Game="sse"
Output="Scripts"
Optimize="false"
Release="false"
Final="false"
Anonymize="true"
>
<Imports>
<Import>.\Source\Scripts</Import>
<Import>e:\Program Files (x86)\Steam\steamapps\common\Skyrim Special Edition\Data\Source\Scripts</Import>
<Import>e:\Program Files (x86)\Steam\steamapps\common\Skyrim Special Edition\Data\Scripts\Source</Import>
</Imports>
<Folders>
<Folder>.\Source\Scripts</Folder>
</Folders>
</PapyrusProject>