0% found this document useful (0 votes)
69 views17 pages

Money Cheat Mod

Uploaded by

Juan Perez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views17 pages

Money Cheat Mod

Uploaded by

Juan Perez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

CHAPTER 10

Money Cheat Mod


This chapter will explore making a money cheat which will allow players to
give themselves unlimited amounts of in-game money (see Figure 10-1).
This mod may also be useful for testing other mods you make as you will
be able to make any purchases from the shop or upgrades without concern
for money. Furthermore, you will need to learn how to make it so players
can interact with placeable objects in the environment. Let’s start!

Figure 10-1. Running out of money? Fear no more!

© GIANTS Software GmbH 2024 255


Z. Brumbaugh and M. Leithner, Scripting Farming Simulator with Lua,
[Link]
Chapter 10 Money Cheat Mod

Technical Requirements
Like the previous chapter, you will be working entirely in the GIANTS
Editor and Studio and must meet the requirements mentioned in the
“Technical Requirements” section of Chapter 2, “Getting Started with the
GIANTS Editor.” Make sure you are always using the most recent version of
the GIANTS Editor. This will ensure that you are able to take advantage of
any new features. You can find all the code and assets used in this chapter
in the book’s code repository on the GDN at the following link:

[Link]

Creating Mod Scripts


This section will explore all of the scripts necessary for this mod. We will
start by looking at the .xml files and then cover the .lua files. Please see
the “Preparing the Mod Folder Structure” section of Chapter 5, “Making
a Diner with a Rotating Sign,” on how to set up a mod project and use the
sample files provided on GDN.

Creating XML Files


As always, we begin the mod by creating [Link]. Let us explore its
contents:

256
Chapter 10 Money Cheat Mod

<?xml version="1.0" encoding="utf-8" standalone="no" ?>


<modDesc descVersion="72">

      <Author>GIANTS Software</author>
      <version>[Link]</version>
      <multiplayer supported="true" />
      <title>
            <en>Sample Mod - Money Cheat</en>
      </title>
      <description>
            <en>A sample mod</en>
      </description>
      <iconFilename>icon_moneyCheat.png</iconFilename>
      <placeableSpecializations>
            <specialization name="atm" className="PlaceableATM"
                  filename="scripts/[Link]" />
      </placeableSpecializations>
      <placeableTypes>
            <type name="atm" parent="simplePlaceable"
                        filename="$dataS/scripts/placeables/
[Link]">
                  <specialization name="atm" />
            </type>
      </placeableTypes>
      <extraSourceFiles>
            <sourceFile
filename="scripts/events/[Link]"/>
      </extraSourceFiles>
      <storeItems>
            <storeItem xmlFilename="placeable/[Link]"/>
      </storeItems>
      <l10n filenamePrefix="l10n/l10n" />
</modDesc>

257
Chapter 10 Money Cheat Mod

After defining the basic fields of the mod, we define a specialization in


the placeableSpecializations field called PlaceableATM. In our mod, players
will be able to get the money from a physical ATM, so they will need to buy
the ATM and place it down.
We will define the PlaceableATM specialization in the “Creating
Lua Files” section of this chapter. Following this, we set the ATM to be
placeable by using the placeableTypes field and using the functionality of
the Placeable base class.
Additionally, we add our previous defined specialization to add the
features of the ATM script. In the extraSourceFiles field, we also include
[Link], which will also be defined in the next section. In the
storeItems field, we include a reference to [Link], which we will define
later in this section.
Finally, we define the l10n element which is used for referencing
translation files.
Next, we will define the [Link] file which holds the configurations for
the ATM. We will now look at the contents of the file:

<?xml version="1.0" encoding="utf-8" standalone="no" ?>


<placeable type="atm" xmlns:xsi="[Link]
XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://
[Link]/fs22/[Link]">
      <storeData>
            <name>ATM</name>
            <functions>
                  <function>An ATM to get Money</function>
            </functions>
            <image>placeable/store_atm.png</image>
            <price>1500</price>
            <lifetime>1000</lifetime>
            <rotation>0</rotation>
            <brand>NONE</brand>
            <species>placeable</species>

258
Chapter 10 Money Cheat Mod

            <category>decoration</category>
            <brush>
                  <type>placeable</type>
                  <category>decoration</category>
                  <tab>uncategorized</tab>
            </brush>
            <vertexBufferMemoryUsage>0</
vertexBufferMemoryUsage>
            <indexBufferMemoryUsage>0</indexBufferMemoryUsage>
            <textureMemoryUsage>0</textureMemoryUsage>
            <instanceVertexBufferMemoryUsage>0</
instanceVertexBufferMemoryUsage>
            <instanceIndexBufferMemoryUsage>0</
instanceIndexBufferMemoryUsage>
</storeData>

We again start with the XML declaration of the placeable root element.
We define ATM to be of the placeable type, so the system knows the feature
set of the object. In the storeData field, we include the information relevant
to the item being displayed in the store. This includes the price, image,
function, and other basic information about the ATM. You can refer to the
“Creating XML Files” section of Chapter 5, “Making a Diner with a Rotating
Sign,” where we first use this field. Let us continue:

    <base>
        <filename>placeable/atm.i3d</filename>
    </base>
    <placement useRandomYRotation="false"
useManualYRotation="true" >
        <testAreas>
            <testArea startNode="testArea1Start"
endNode="testArea1End" />
        </testAreas>
    </placement>

259
Chapter 10 Money Cheat Mod

In the base element, we include the relative path from the mod
directory to the .i3d file containing the ATM. Next, we configure placement
for the ATM via the placement field. In this field, we reference nodes on the
model to determine whether an object obstructs the area the player wants
to put the ATM.

<clearAreas>
      <clearArea startNode="clearArea1Start"
widthNode="clearArea1Width"
            heightNode="clearArea1Height"/>
</clearAreas>
<leveling requireLeveling="true" maxSmoothDistance="10"
maxSlope="75"
      maxEdgeAngle="30" >
      <levelAreas />
</leveling>
<indoorAreas />

In the clearAreas field, we set the area the ATM is placed to be clear of
foliage and other environmental objects.

<ai>
      <updateAreas>
            <updateArea startNode="testArea1Start"
endNode="testArea1End" />
      </updateAreas>
</ai>

In the ai field, we mark the area as blocked so autonomous equipment


and other AI will avoid the ATM. We will now cover the remaining portion
of the file:

<atm moneyPerAction="15000">
      <trigger node="playerTrigger" />
      <sounds>

260
Chapter 10 Money Cheat Mod

            <action file="sounds/[Link]"
innerRadius="5.0" outerRadius="15.0"
                  fadeOut="0.1" linkNode="playerTrigger">
                  <volume indoor="0.45" outdoor="1.1" />
                  <pitch indoor="1.0" outdoor="1.0" />
            </action>
      </sounds>
</atm>
<i3dMappings>
      <i3dMapping id="playerTrigger" node="0>0|0" />
      <i3dMapping id="clearArea1Start" node="0>1|0" />
      ...
</i3dMappings>
</placeable>

The file concludes with a custom element for the mod called atm. In
this element, we define the amount of money the player receives when
they interact with the ATM via the moneyPerAction field, which holds
a value of 15000. You can change this value to however much you want
players to receive. The trigger element references a trigger shape in our
i3d file. It is later used to notify a script if a player is close to the ATM. We
also include a satisfying sound when the ATM is used by the player and
they receive their money. Lastly, we include the i3d mappings inside of the
i3dMappings field.
We will now create translation files for text we want to display to the
user about the ATM. For English, we will define a file called l10n_en.xml.
Let us now look at the file:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>


<l10n>
      <elements>
            <e k="action_atmRequest" v="Draw Money"/>
      </elements>
</l10n>

261
Chapter 10 Money Cheat Mod

In the file, we simply include the text that should be associated with the
ATM interaction. In this case, we want to tell the player that by interacting
with the ATM they will Draw Money.
Let us now look at the contents of the German translation file, l10n_de.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>


<l10n>
      <elements>
            <e k="action_atmRequest" v="Geld abheben"/>
      </elements>
</l10n>

Like in the file for English, we include the text that describes the action
with the ATM. This concludes all of the .xml files for the mod. In the next
section, we will look at the .lua files we need to create.

Creating Lua Files


The first file we will create is [Link], which builds on the base Event
class. Let us now cover the file’s contents:

ATMEvent = {}
local ATMEvent_mt = Class(ATMEvent, Event)
InitEventClass(ATMEvent, "ATMEvent")
function [Link]()
      local self = [Link](ATMEvent_mt)
      return self
end
function [Link](placeable, farmId)
      local self = [Link]()
      [Link] = placeable
      [Link] = farmId
      return self
end

262
Chapter 10 Money Cheat Mod

We start by creating two constructors with one that takes no arguments


and one that takes a placeable object and farm ID. If the object and ID are
passed to the constructor, then they are assigned to placeable and farmId
fields within the class.

function ATMEvent:writeStream(streamId, connection)


      [Link](streamId, [Link])
      streamWriteUIntN(streamId, [Link],
            FarmManager.FARM_ID_SEND_NUM_BITS)
end
function ATMEvent:readStream(streamId, connection)
      [Link] = [Link](streamId)
      self.farmId = streamReadUIntN(streamId, FarmManager.
FARM_ID_SEND_NUM_BITS)
      self:run(connection)
end

Like in other chapters, the readStream() and writeStream() functions


are used to send and process updates to the network stream. In the
readStream() function, we update the placeable and farmId fields with
what has been written to the stream.

function ATMEvent:run(connection)
      assert(not connection:getIsServer(),
"ATMEvent is client to server only")
      if [Link] ~= nil then
            [Link]:requestMoney([Link])
      end
end

Lastly, the run() function calls the requestMoney() function of


the placeable object associated with the event. This function will be
implemented in the PlaceableATM specialization, which we will define in
this section.

263
Chapter 10 Money Cheat Mod

With [Link] complete, we are ready to define PlaceableATM.


lua, the main component of the mod. Let us now look through its contents:

local modName = g_currentModName


PlaceableATM = {}
PlaceableATM.SPEC_TABLE_NAME = "spec_"..modName..".atm"
function [Link](schema, basePath)
      schema:setXMLSpecializationType("ATM")
      schema:register(XMLValueType.NODE_INDEX,
basePath .. ".[Link]#node",
            "Node index or i3d mapping name of the
trigger shape")
      schema:register([Link],
basePath .. ".atm#moneyPerAction",
            "The amount of money a player gets", 100000)
      [Link](schema,
            basePath .. ".[Link]", "action")
      schema:setXMLSpecializationType()
end
function [Link](specializations)
      return true
end

We begin the specialization by defining the default functions. After


defining the namespace for the mod, we include the registerXMLPaths()
function which registers elements from the XML files with the placeable
schema. Next, we add the prerequisitesPresent() function. Because we do
not require any prerequisites, we simply return true.

function [Link](placeableType)
      Specia[Link](placeableType,
"onLoad", PlaceableATM)

264
Chapter 10 Money Cheat Mod

      Specia[Link](placeableType,
"onDelete", PlaceableATM)
end
function [Link](placeableType)
      Specia[Link](placeableType,
"onATMTriggerCallback",
            [Link])
      Specia[Link](placeableType,
"requestMoney",
            [Link])
end

The registerEventListeners() function registers the onLoad() and


onDelete() functions of the mod. These functions will be implemented
later in the script. Lastly, the registerFunctions() function registers our
custom onATMTriggerCallback() and requestMoney() functions, which will
be added later in the file. Let us continue through the script:

      function PlaceableATM:onLoad(savegame)
      local spec = self[PlaceableATM.SPEC_TABLE_NAME]
      local node = [Link]:getValue("[Link].
trigger#node", nil, [Link], self.i3dMappings)
      if node ~= nil then
            addTrigger(node, "onATMTriggerCallback", self)
            [Link] = node
            [Link] = [Link](self, node)
            [Link] = [Link]:getValue(
                  "[Link]#moneyPerAction", 100000)
            [Link] = {}
            spec.s[Link] =
g_soundManager:loadSampleFromXML([Link],
                  "[Link]", "action", self.
baseDirectory, [Link], 1,
                  [Link], self.i3dMappings, self)

265
Chapter 10 Money Cheat Mod

      else
            [Link]([Link], "Missing atm
trigger!")
      end
end

The onLoad() function starts by referencing the node the player


triggers to receive the money. If the node exists, then we add an interaction
trigger that calls the onATMTriggerCallback() function when triggered. A
shape within the i3d can be marked as a trigger shape in the editor.
Triggers are a part of the physics system, so this shape also has to be
a physics shape. Normally, it should have the rigidbody type STATIC or
KINEMATIC. It is also important to set the correct collisionMask of the
shape; otherwise, the script may not fire any trigger callback because the
physics engine does not detect any collisions.
The node is then assigned to the triggerNode field of the class. We also
assign an Activatable object to the activatable field of the class. Activatable
objects are script objects that are handled by the ActivatableObjectsSystem
and used to tell the system that the player is within a given area where
they can activate or trigger a specific action. From [Link], we retrieve
the value for how much money the player should get per interaction and
assign it to the moneyPerAction field. Finally, we load the interaction
sound into the samples field of the class.

function PlaceableATM:onDelete()
local spec = self[PlaceableATM.SPEC_TABLE_NAME]
if [Link] ~= nil then
      removeTrigger([Link])
      local system = g_currentMission.activatableObjectsSystem
      system:removeActivatable([Link])
      g_soundManager:deleteSamples([Link])
end
end

266
Chapter 10 Money Cheat Mod

The onDelete() function will clean up the class when the ATM is
deleted by checking that the trigger node exists and if so removing the
trigger callback, the activatable object, and the trigger sound.
Let us now explore our custom functions:

function PlaceableATM:onATMTriggerCallback(triggerId, otherId,


onEnter, onLeave, onStay, otherShapeId)
      if onEnter or onLeave then
            if g_currentMission.player ~= nil and
                  otherId == g_currentMission.player.
rootNode and
                  g_currentMission.[Link] ~=
FarmManager.SPECTATOR_FARM_ID
             then
                  local spec =
self[PlaceableATM.SPEC_TABLE_NAME]
                  local activatableSystem =
g_currentMission.activatableObjectsSystem
                  if onEnter then
                        activatableSystem:addActivatable(
[Link])
                  else
                        activatableSystem:removeActivatable(
[Link])
                  end
            end
      end
end

The onATMTriggerCallback() function is passed whether the player


is entering or leaving the trigger area. If the player is leaving or entering
the area, then we check that the player is actually present and display or
remove the trigger accordingly. The second parameter of the callback holds

267
Chapter 10 Money Cheat Mod

the entity ID of the colliding physics shape. We can use it to determine


if the shape is a player or not by simply comparing it with the player
rootNode. Let us continue:

function PlaceableATM:requestMoney(farmId)
      local spec = self[PlaceableATM.SPEC_TABLE_NAME]
      g_soundManager:playSample([Link])
      if not [Link] then
            g_client:getServerConnection():sendEvent(
[Link](self, farmId))
            return
      end
      local amount = [Link]
      local moneyType = [Link]
      local addChange = true
      local forceShow = true
      g_currentMission:addMoney(amount, farmId, moneyType,
            addChange, forceShow)
end

The requestMoney() function will play the trigger sound and, if we are
on the client, send a request to the server to dispense money. The handling
and syncing of money are done on the server only, and the balance is not
allowed to be changed on the client. As such, we need to tell the server that
we requested money.
We do so by sending the ATMEvent to the server and leave the function
by calling return afterward. So, if this function is being run on the server,
then it will add the specified amount of money to the player’s balance. The
addMoney() function takes the amount of money that should be added or
subtracted and the ID of the farm that the change should be applied to.
The money type is mostly used for the statistics of the game. The
addChange and forceShow flags tell the system if the money change should
be shown immediately using the in-game notifications in the top-­right

268
Chapter 10 Money Cheat Mod

corner of the HUD or if the system should sum all calls up until an explicit
call with forceShow = true occurs. We will now cover the remaining
contents of the file:

ATMActivatable = {}
local ATMActivatable_mt = Class(ATMActivatable)
function [Link](placeable, triggerNode)
      local self = setmetatable({}, ATMActivatable_mt)
      [Link] = placeable
      [Link] = triggerNode
      [Link] = g_i18n:getText("action_atmRequest")
      return self
end
function ATMActivatable:getIsActivatable()
      if g_gui.currentGui ~= nil then
            return false
      end
      returng_currentMission.[Link] ~= FarmManager.
SPECTATOR_FARM_ID
end
function ATMActivatable:getDistance(x, y, z)
      local tx, ty, tz = getWorldTranslation([Link])
      return MathUtil.vector3Length(x-tx, y-ty, z-tz)
end
function ATMActivatable:run()
      [Link]:requestMoney(g_currentMission.
[Link])
end

We create ATMActivatable to be a new class. For this class, we include


a constructor that takes a placeable object and trigger node. The placeable
object and trigger node are respectively assigned to the placeable and
triggerNodes fields of the ATMActivatable class. We also set the activateText

269
Chapter 10 Money Cheat Mod

field to the action text defined in the translation file. The getIsActivatable()
function checks whether the player can currently request money.
The getDistance() function returns the distance to the activatable
object and is used to prioritize actions if multiple activatables are in range.
Finally, we define the run() function which will call the requestMoney()
function of the object held in the placeable field. This concludes all of the
programming required for this mod. Like with the other chapters, take a
moment to review what you have accomplished and written and how these
concepts may apply to future mods.

Testing the Mod


With the scripts for your mod now created, you are ready to begin testing.
First, start a new game and select a map of your choice. Make sure that
you have your mod selected to be used in the game. Once the game
had loaded, open the Construction screen. Go to the miscellaneous
category and place the ATM. If your mod has been created correctly, you
should be prompted to withdraw money in the amount you set in the
configuration file.

Summary
In this chapter, you learned how to create an ATM that dispenses a
predetermined amount of money to the player. Importantly, you learned
how to use activatable objects to trigger functions when a player interacts
with an object within a certain distance.
In the next chapter, you will learn to make your mods available to other
players and members of the Farming Simulator community by publishing
your creations to the ModHub.

270
Chapter 10 Money Cheat Mod

Open Access This chapter is licensed under the terms


of the Creative Commons Attribution 4.0 International
License ([Link] which permits
use, sharing, adaptation, distribution and reproduction in any medium or
format, as long as you give appropriate credit to the original author(s) and
the source, provide a link to the Creative Commons license and indicate if
changes were made.
The images or other third party material in this chapter are included
in the chapter's Creative Commons license, unless indicated otherwise
in a credit line to the material. If material is not included in the chapter's
Creative Commons license and your intended use is not permitted by
statutory regulation or exceeds the permitted use, you will need to obtain
permission directly from the copyright holder.

271

You might also like