The maps in our most beloved game are quite detailed. Modders put in quite an effort to make the place feel realistic. Houses have all kinds of furniture, with bathrooms and kitchens, there are bookshelves, computers and so on. Sadly, we can't really do anything with the stuff. All we can do is sometimes open structures to get hidden items, and open doors. That is okay, but... well... not that much.
This feature attempts to change that. The idea is simple: You rightclick with your mouse. As usual, your cursor will transform to 'force' an action. If you then hover over structures, they show you whether a special action is possible. Click on the structure, and the merc will do whatever is possible here.
The special trick is that which actions are possible where, and what they do, can be fully defined in xml and lua. I basically provide a base structure for this - what can happen where with what is up to the modders.
So far, the following actions exist:
Hacking - hack a computer
Read file - read the contents of bookshelves and file cabinets
Drink from a water tap - drinking from a water tap or sink restores breath and stills your thirst
I will go into more detail on these actions in the following posts.
The actions themselves are defined in the new xml TableData\Map\InteractiveActions.xml. You can find more details on what tags exist and how they work in there.
If you want something specific to happen on an interaction with a specific structure (for example, hacking a specific computer should give you a specific text), you can set a LUA Id. A lua script - HandleInteractiveActionResult() in Overhead.lua - will be called. You can then set whatever you want to happen in there as a result of the interaction. The stock script also contains quite a few detailed examples, so look for inspiration there.
The interesting thing is that you can define actions both very broadly and very precise. So you can set all structures of a tileset to yield result A, but not in sector X, where the result should be B. Apart from that one specific one, which should give you C. And so on and so on. I've recently added a way for modders to store their own data. This is extremely useful for this feature - you can 'remember' what actions were already taken, and alter your results accordingly. For example, hacking a computer might yield you a few dollars - but of course only the first time. The stock script also uses this extensively, so look there for inspiration.
Keep in mind that the code only provides a base structure. What you do in LUA is up to you. If you want to be able to hack a tree to spawn tanks that recite Macbeth, you are free to do so.
This feature is fully savegame compatible.
This feature has been added to the trunk in r8278 & GameDir r2333. Using the new exe without the new GameDir will cause you to forever live in the twilight. You will walk the earth, neither dead or alive. Sorrow shall be your nourishment, regret being your only companion.
[Updated on: Sun, 11 December 2016 14:31]
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
The first action I've added is hacking. When the cursor looks like this, you can hack something:
Note that this is a multi-turn-action. You will need several truns to finish this - in realtime this will happen instantly. Hacking requires skill, and for that there is a new background property:
...
<hackerskill>0</hackerskill> <!-- hacker skill, 0 to 100. Value > 0 means we can hack computers -->
...
<!-- Gumpy -->
<BACKGROUND>
<uiIndex>45</uiIndex>
<szName>Harvard graduate</szName>
<szShortName>Harvard graduate</szShortName>
<szDescription>University taught you many things, but combat isn't one of them.</szDescription>
<leadership>-5</leadership>
<ap_fortify>10</ap_fortify>
<disarm_trap>20</disarm_trap>
<traplevel>1</traplevel>
<resistance_suppression>-10</resistance_suppression>
<insurance>50</insurance>
<hackerskill>60</hackerskill>
<no_male>1</no_male>
<no_female>1</no_female>
</BACKGROUND>
...
Our hacking skill can be improved by a percentage multiplier that we can gain from items:
...
<ITEM>
<uiIndex>1021</uiIndex>
<szItemName>Laptop</szItemName>
<szLongItemName>Laptop</szLongItemName>
<szItemDesc>This thing just crashes with a blue screen when you boot it up. It might be the humidity. It might just be Windows.</szItemDesc>
...
<usHackingModifier>50</usHackingModifier>
...
</ITEM>
...
We only get bonus from one item per inventory, and the bonus is influenced linearly by item status. So if Ears has a hacking skill of 30 and a laptop with status 80 in his inventory, his skill will be 30 * (1 + 0.5 * 0.8) = 42.
As a result, only people with the hacking skill can hack computers. Per default, the following mercs have gained this ability:
Barry (10)
Gumpy (60)
Fredo (50)
Speck (80)
Sparky (20)
Ears (30)
I am open to give this ability to more people, but I am not inclined to give it to any top-mercs. I see none that would fit, honestly. besides, hacking isn't strictly required for the game - though I added a few rather nice boni if you do so.
Speaking if adding stuff - I've identified 42 computers in the stock maps, and have added unique events for all of them in HandleInteractiveActionResult() in Overhead.lua. Yes, that took me quite a while. So hacking will always provide some result - on some computers, just a bit of 'lore'-building (for example, hacking a computer in Orta might give you more info on the rocket rifles). Other computers allow you to get info on enemy personnel, or even allow you to earn money.
As each action can have an unique diffulty level, some hackers might only be able to hack some computers. Speck can hack into things Barry has no chance of breaching.
Keep in mind that you can define in the xml what can be hacked an what can't. It's reasonable to apply this to computers, but it you want to hack a tree - that's only a xml change away.
Read file
Similar to hacking, the idea is to 'read' books from a book shelf, or or files from a file cabinet. I've added a few examples, but haven't provided an unique event for each of them. Given the number of book shelves in Arulco, I wanted to rather finish the feature this month :-)
Our reading skill is our wisdom stat.
Drink from a water tap
Allows 'drinking' from a structure. You will regain breath. If food feature is turned on, you can gain drink points. If disease is on and the sector's water is poisoned, you have a chance to get a disease.
Of course you can define this action on toilets, too .
Robots and vehicles have a water drinking skill of 0. Anybody else has 100 - we are pros at drinking water.
Buy soda
As demonstrated by Ivan in the video - you insert money, and get a soda can.
Note that the soda you get will be the first item with the new 'SODA'-flag, which is <ItemFlag>134217728</ItemFlag>.
We are also pros at buying soda, unless our war chest doesn't cover the measly $3 required for it. That would be quite embarassing.
Play a minigame
Another feature added in r8346 & GameDir r2350 allows you to play at arcade machines. So far only Tetris. Perhaps this might change in the future?
Of course, many many more actions are thinkable - depending on what you think of (and whether people are actually willing to draw the cursors and find sounds instead of making me do all the work and then whining about the bad art), I might add more.
[Updated on: Sun, 11 December 2016 14:30]
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
And yes, one of the comnputers has that as a reward, although getting to that computer is particular tricky, and the hack requires a lot of skill. Tip: Which desktop computer is very hard to get to?
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
Excellent job as always. Can't wait to add an "Unleash army of Termina... I mean, uh, totally generic and free of copyright doombots" option on the royal palace computers.
Question : Would it be possible to make SAM sites hackable? Would be nice to be able to enter the place with the covert ops trait to activate some auto-destruction sequence (Deidranna's basically a Bond villain by now so why not?) or just shot down the thing for a while
The SAM control computers can be hacked too. At the moment your merc will basically tell you that they have no idea how the controls work, so they'd rather not touch anything. I do, however, plan to alter that a bit... the idea would be that hacking would lower the effectivity of a SAM until it is 'rebooted' (either by the army, via ASD, or by your mercs). That woudl require a few new variables and a svegame change though, not sure when I'll have time for that.
As to blowing it up - you can already do that. If you destroy the SAM control computer, the SAM will stop working (that is actually a vanilla mechanism).
@all: modders, like edmortimer, might want to take a closer look at the lua function in Overhead.lua. Some of the hack results are possible threads of possible quests one can think of. For example, one computer in Alma prison would give you 'video evidence' of prison torture. The idea is that if we give that evidence to, say, the UN, and we've retrieved it in secret, the UN would sanction the regime, giving us some boni (this basically ties into the 'outside organisations' idea I had).
Another quest would be intercepting an army intelligence server - one of the computers inn Alma HQ gives you a list of 'notable rebels', and what the army knows of them. This can be used for lore, and a possible new quest (by hinting that one of the 'other' rebels referred to in those files was a traitor - hack a computer in Meduna to find out more).
Or we could simply retrieve a possible list of people secretly working with the queen to extort them. Same for Kingpin.
Just food for thought.
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
I know but I like the idea of hacking the thing into blowing up the whole site (Maybe it could make it completely unusable forever as a twist, forcing you to use manpads to bring the army's helicopters down during the late game...)
Would make it easier than outright blowing it up with a spy though, unless hacking is considered a suspicious action...
By the way, does the Tech Whiz trait allow one to hack stuff? I feel like it should...
Hacking is given to those people where some affinity to computer-related shenanigans can at least be justified. I don't see why someone good at impersonating people should be a hacker. You can always alter backgounds the way you like, anyway.
Opening doors is theoretically doable, but I don't know whether there is a lua function for that (afaik, there is no documentation of what lua functions exist, and what the existing functions do, anyway).
@Slax: well... I do have some ideas for some easter eggs, but nothing so simple. Have to see...
Well, yes, that background could use hacking. Then again, the backgrounds could all use some reworks. Some have way too many properties for more liking.
Need more time.
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
JA2_EN_Debug.exe!std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15 C++
JA2_EN_Debug.exe!std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > >::_Compat(const std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > & _Right) Line 238 + 0x14 bytes C++
JA2_EN_Debug.exe!std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > >::operator==(const std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > & _Right) Line 203 C++
JA2_EN_Debug.exe!std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > >::operator!=(const std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > & _Right) Line 208 + 0xc bytes C++
JA2_EN_Debug.exe!std::vector<unsigned short,std::allocator<unsigned short> >::erase(std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > _First_arg, std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > _Last_arg) Line 1194 + 0xc bytes C++
JA2_EN_Debug.exe!std::vector<unsigned short,std::allocator<unsigned short> >::clear() Line 1218 + 0xaa bytes C++
JA2_EN_Debug.exe!INTERACTIVE_STRUCTURE::reset() Line 133 C++
> JA2_EN_Debug.exe!ReadInInteractiveActionsStats(char * fileName) Line 240 C++
JA2_EN_Debug.exe!LoadExternalGameplayData(char * directoryName) Line 396 + 0xc bytes C++
JA2_EN_Debug.exe!InitializeJA2() Line 1456 + 0x11 bytes C++
JA2_EN_Debug.exe!InitScreenHandle() Line 472 + 0x5 bytes C++
JA2_EN_Debug.exe!GameLoop() Line 398 + 0x12 bytes C++
JA2_EN_Debug.exe!SGPGameLoop() Line 1940 C++
JA2_EN_Debug.exe!CallGameLoop(bool wait) Line 1983 C++
JA2_EN_Debug.exe!TimerActivatedCallback(int timer, void * state) Line 905 + 0x7 bytes C++
JA2_EN_Debug.exe!InnerTimerNotify(int timer) Line 668 + 0x36 bytes C++
JA2_EN_Debug.exe!BroadcastTimerNotify(int timer) Line 678 + 0x10 bytes C++
JA2_EN_Debug.exe!JA2NotifyThread(void * lpParam) Line 334 + 0x7 bytes C++
kernel32.dll!76e238f4()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77e65de3()
ntdll.dll!77e65dae()
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
JA2_EN_Debug.exe!std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15 C++
JA2_EN_Debug.exe!std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > >::_Compat(const std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > & _Right) Line 238 + 0x14 bytes C++
JA2_EN_Debug.exe!std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > >::operator==(const std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > & _Right) Line 203 C++
JA2_EN_Debug.exe!std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > >::operator!=(const std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > & _Right) Line 208 + 0xc bytes C++
JA2_EN_Debug.exe!std::vector<unsigned short,std::allocator<unsigned short> >::erase(std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > _First_arg, std::_Vector_const_iterator<std::_Vector_val<unsigned short,std::allocator<unsigned short> > > _Last_arg) Line 1194 + 0xc bytes C++
JA2_EN_Debug.exe!std::vector<unsigned short,std::allocator<unsigned short> >::clear() Line 1218 + 0xaa bytes C++
> JA2_EN_Debug.exe!INTERACTIVE_STRUCTURE::reset() Line 133 C++
JA2_EN_Debug.exe!interactiveactionsStartElementHandle(void * userData, const char * name, const char * * atts) Line 56 C++
JA2_EN_Debug.exe!_XML_Parse() + 0x325d bytes C
JA2_EN_Debug.exe!_XML_Parse() + 0x3d9f bytes C
JA2_EN_Debug.exe!_XML_Parse() + 0x541b bytes C
JA2_EN_Debug.exe!_XML_Parse() + 0x5c1a bytes C
JA2_EN_Debug.exe!_XML_Parse() + 0x5e2f bytes C
JA2_EN_Debug.exe!_XML_ParseBuffer() + 0x5c bytes C
JA2_EN_Debug.exe!_XML_Parse() + 0x104 bytes C
JA2_EN_Debug.exe!ReadInInteractiveActionsStats(char * fileName) Line 233 + 0x13 bytes C++
JA2_EN_Debug.exe!LoadExternalGameplayData(char * directoryName) Line 396 + 0xc bytes C++
JA2_EN_Debug.exe!InitializeJA2() Line 1456 + 0x11 bytes C++
JA2_EN_Debug.exe!InitScreenHandle() Line 472 + 0x5 bytes C++
JA2_EN_Debug.exe!GameLoop() Line 398 + 0x12 bytes C++
JA2_EN_Debug.exe!SGPGameLoop() Line 1940 C++
JA2_EN_Debug.exe!CallGameLoop(bool wait) Line 1983 C++
JA2_EN_Debug.exe!TimerActivatedCallback(int timer, void * state) Line 905 + 0x7 bytes C++
JA2_EN_Debug.exe!InnerTimerNotify(int timer) Line 668 + 0x36 bytes C++
JA2_EN_Debug.exe!BroadcastTimerNotify(int timer) Line 678 + 0x10 bytes C++
JA2_EN_Debug.exe!JA2NotifyThread(void * lpParam) Line 334 + 0x7 bytes C++
kernel32.dll!76e238f4()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77e65de3()
ntdll.dll!77e65dae()
Sorry, I'm no developer so I won't be of much help. The code crashes when trying to run tileindexvector.clear( ) inside pData->curArray[pData->curIndex].reset( ).
clear( ) runs function erase( ) which uses begin and end of a vector. The vector isn't initialized yet so begin and end are invalid pointers which causes function erase( ) to crash. At least that is how it looks to me.
Hmpf. Try r8283 then. That behaviour of VS2010 crashing while VS2013 doesn't complain even if all possible exceptions are thrown irks me to no small amount.
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
Hmpf. Try r8283 then. That behaviour of VS2010 crashing while VS2013 doesn't complain even if all possible exceptions are thrown irks me to no small amount.
Unfortunately r8283 didn't fix it but I was able to fix it myself now. VS2010 debug builds don't like it if you try to assign empty vectors. So now we first check if the vector actually has content and only then we assign it. It's somewhat like the NULL pointers that can happily crash the code as well.
I like this feature very much and was trying to expand a bit by doing interactive stoves but I was unable to find how to create and delete an item from the mercs inventory, my idea was to create a interactive stove where you can cook so the food could give you a bit more morale than the usual.
Click on the structure, and the merc will do whatever is possible here.
Is it possible to externalize this more?
InteractiveAction.xml
what kind of action is possible here?
sActionType
0: nothing
1: hack a computer
2: read a file from a file cabinet
3: take water from a water tap
4: buy soda from a soda machine
5: play a minigame
I was thinking about a way to define those action-types in xml (or lua), at least to some degree.
Something like:
a vending machine, where we can define which item will be given out, defining how much money is to spent, which cursor should be used and which sound should be played (where sound and cursor be chosen from file not code). This way, the one modding can be left responsible to provide cursor and sound.
or general interacting, where interacting with graphic on map would trigger the animation-frames inside and a sound plays.. Where location of sti and jsd have to be defined by modder , as well as number of animation-frame and name of sound-file in folder sounds. This could be the standard hand-cursor, or one to be defined and added by modder. (Somehow simular to how doors run swing-open animation). And/or allow to connect this to facts from moddingFacts from lua. This way we could produce for example stuff like the radarscreen in Sam-Sites "show" something when interacted, or a table with a radio on it can play a short interference-sound, or a barrier can swing up, and-so-on-and-on... and with connection to lua facts things like intel, morale, etc. could be done too.
I just made up, what I think should be defined for this without having any coding-knowledge, so sorry if this files under complete bull, but if not, would it be possible?
EDIT:
Asdow wrote on Sat, 15 February 2020 21:52
where
'name' is used in LogicalBodyTypes.xml to select a specific animation
'file' points to the file where the animation data is stored. By default, the code looks for these in the 'Data' folder, so the actual path in the example is Data/Anims/LOBOT/RGM/animationfile.sti
'flags' unknown currently, it's used somewhere in the code, but it has not been relevant so far in our quest to get this working in the first place
'structdata' tells what .JSD file to use for the anim, if any. In a merc's case, it's pretty much dependent on what stance is the animation supposed to be for.
'directions' how many directions does the animation have. For merc's it's pretty much always 8
'framesperdir' How many frames per direction is in the animation. New animations *must* have the same amount of frames per direction as the underlying animation. Otherwise bad things happen!
'profile' unknown currently. Same thing as with flags, wasn't relevant to get this working.
This one lead to my assumption, that sti and jsd can be addressed for starting animations. Again, that's just a non-coding persons hillarious request, don't intend to tell anybody to do what I can't.
This is a great variety of gameplay!
However, I want to note that the text displayed on the screen is written in the Overhead.lua code itself, which makes it difficult to translate into other languages. Are you planning to change the data structure so that the text is more convenient for translation?
We can ask the game what language we are currently using while using lua scripts.
-- these numbers aren't used in the code - we only use them in LUA
Languages =
{
LANGUAGE_ENGLISH = 0,
LANGUAGE_GERMAN = 1,
LANGUAGE_RUSSIAN = 2,
LANGUAGE_DUTCH = 3,
LANGUAGE_POLISH = 4,
LANGUAGE_FRENCH = 5,
LANGUAGE_ITALIAN = 6,
LANGUAGE_CHINESE = 7,
}
if ( GetUsedLanguage( nil ) == Languages.LANGUAGE_ENGLISH ) then
SetScreenMsg(FontColour.FONT_MCOLOR_LTGREEN, "The prisoners are very grateful for freeing them.")
elseif ( GetUsedLanguage( nil ) == Languages.LANGUAGE_GERMAN ) then
SetScreenMsg(FontColour.FONT_MCOLOR_LTGREEN, "Die Gefangenen sind für die Befreiung sehr dankbar.")
else
SetScreenMsg(FontColour.FONT_MCOLOR_DKRED, "Translation missing!")
end
So translations are easily doable. Provided there is some poor soul willing to do the work
[Updated on: Sat, 30 May 2020 19:26]
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
@Flugente why not use enumed localized string values, like in the code? This would allow much easier translation and much more compact lua code. Except that it's a lot of tedious work to externalize everything.
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
As of r9125 & GameDir r2596, we now have a generic 'various' entry for a bunch of interactions. I added sounds to play for billiard tables/table tennis/toilets/urinals/television, with a new cursor icon, a moving gearwheel.
InteractiveActions.xml:
sActionType what kind of action is possible here?
0: nothing
1: hack a computer
2: read a file from a file cabinet
3: take water from a water tap
4: buy soda from a soda machine
5: play a minigame
6: various
...
<!-- |||||||||||||||||||| VARIOUS |||||||||||||||||||| -->
<!-- billiard table -->
<ACTION>
<szTileSetName>m-furn4.sti</szTileSetName>
<usTileIndex>12</usTileIndex>
<usTileIndex>13</usTileIndex>
<sActionType>6</sActionType>
<luaactionid>52</luaactionid>
</ACTION>
Overhead.lua:
elseif ( usActionType == ActionTypes.ACTIONTYPE_VARIOUS ) then
if ( sLuaactionid == InteractiveAction.BILLIARD ) then
PlaySound("Sounds\\billiard.wav")
elseif ( sLuaactionid == InteractiveAction.TABLETENNIS ) then
PlaySound("Sounds\\tabletennis.wav")
...
None of this is actually new code, this was already possible, but perhaps this gets some ideas rolling?
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
...
elseif ( sLuaactionid == InteractiveAction.PICTURE_NEONTHECLUB ) then
-- The first argument is the path of a .png picture (any other format will be ignored).
-- The second argument determines whether we stretch the picture to fullscreen (1) or not (0). If the picture is larger than our screen, we stretch it anyway.
-- Only call this function from tactical (the call will be ignored otherwise).
DisplayPictureTactical("Interface\\neonsign_theclub.png", 1)
...
I've added the pictures seen in the video. What's also new about this is that we can now perform interactive actions on decals and decorations in walls, which wasn't possible before (I refer to the decals set via map editor here, not the dynamic ones I added in [url=http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=24858&goto=363425&#msg_363425]dynamic decals[/url]).
This was more tricky than it sounds, but now we can add pictures for, well, pictures.
Rejoice! Never before has there been a better justification to google topless nudes to find the perfect match for a 5x5 pixel porn image we're pretty sure exists in the tilesets somewhere! It's a community service now!
[Updated on: Wed, 07 July 2021 23:14]
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.
We interrupt this thread for a mandatory educational video from the Arulco fire department:
As seen above, we can now use fire extinguishers (item #1761) as of r9141 & GameDir r2602. They are pretty useless as a gun, but pretty awesome at stopping fires.
Due to the frankly bizarre way decals are handled, this requires replacing wall tiles in the lua script, as otherwise removing the fire extinguisher removes the entire wall section.
elseif ( sLuaactionid == InteractiveAction.TAKE_FIRE_EXTINGUISHER_1 ) then
-- 1761 fire extinguisher
CreateItemInvOrFloor(ubID, 1761)
-- due to the way structures are handled, we the decal is on a tile next to the one we are handling, so account for that
-- the empty wall is in another tileset
DestroyAndReplaceDecal(sGridNo - 1, "build_29.sti", 6)
elseif ( sLuaactionid == InteractiveAction.TAKE_FIRE_EXTINGUISHER_2 ) then
CreateItemInvOrFloor(ubID, 1761)
-- due to the way structures are handled, we the decal is on a tile next to the one we are handling, so account for that
-- the empty wall is in another tileset
DestroyAndReplaceDecal(sGridNo - 160, "build_29.sti", 9)
Wall decals actually belong to the structure 'behind' the wall. But as I also require the merc to be able to see the structure they're interacting with, that would mean we could interact with decals through the wall, which, nope. Therefore we have to the aboe hoop with the odd gridno offsets. 160 in the second case refers to the number of columns in the map, so in Bigmaps we'd need to set 360 here.
[Updated on: Tue, 13 July 2021 22:56]
I know now that it could never work between us, as much as we wanted to, it could never be! Not because you're a rabbit, but because you're black.
If you want, you can donate to me. This will not affect how and what I code, and I will not code specific features in return. I will be thankful though.