DavidW
-
Posts
7,984 -
Joined
-
Last visited
Content Type
Forums
Events
Downloads
Gallery
Mods
News
Store
Posts posted by DavidW
-
-
I've just updated it. Should work fine on v247 now.
-
Should be fine (iirc). WEIDU is basically backwards-compatible, there's just this tiny unfortunate exception.
-
Yes. (And various intermediates; e.g. my recode of Ascension is nothing like as abstracted as SCS but still does things at a fairly high level.)
-
Well, just being Turing-complete, by itself, isn't enough to make a programming language fit for a given purpose. Turing machines are Turing-complete, but I'm not planning to mod with them! My point was that WEIDU actually is a fairly powerful programming language, in which you can do most of the things you need for high-level programming.
The actual Turing machine implementation was a joke, mostly. (Obviously WEIDU is Turing complete - all you need for that is variables and basic control flow, and it obviously has those.) But the fact that I can do a fast smooth implementation of a Turing machine in a few dozen lines of WEIDU code and in twenty minutes of my time does provide a reasonable demonstration that WEIDU can easily be used for abstract programming and not just as a low-level interface into IE files.
-
No, I don't think so, precisely because the tape isn't just an output: it's also input and working memory.
(Not that I put more than 5 seconds thought into what it should be called!)
-
Anyone is welcome to use this code in their mods, of course.
-
29 minutes ago, Taylan said:
I still think a language like Python would be beneficial in the long term, but to each their own. We'll have to see if my project goes anywhere; it depends mostly on whether I actually find enough time and energy to put into it.
Oh, you might well be right (though the backwards-compatibility issues are serious). WEIDU is a lot more powerful than it looks, and I actually really enjoy programming in it, but I don't think anyone thinks it's the language that you'd build from scratch for modding.
-
On the question of whether WEIDU is Turing-complete: see here.
-
A somewhat tongue-in-cheek response to the discussion of WEIDU on this thread:
A WEIDU implementation of a Turing machine, using the conventions here:
SpoilerDEFINE_ACTION_FUNCTION turing_machine
INT_VAR display_steps=0
STR_VAR initial_tape=""
machine=""
BEGIN
// initialise array, just in case
ACTION_PHP_EACH turing_tape AS k=>v BEGIN
OUTER_SET $turing_tape("%k%")=0
END
// read the initial_tape into the turing_tape array
OUTER_PATCH "%initial_tape%" BEGIN
FOR (ind=0;ind<BUFFER_LENGTH;++ind) BEGIN
READ_ASCII ind val (1)
SET $turing_tape("%ind%")=val
END
END
// put the pointer at zero
OUTER_SET pointer=0
// initialise the machine
OUTER_SPRINT state "A"
// start the counter
OUTER_SET counter=0
OUTER_WHILE !("%state%" STRING_EQUAL "HALT") BEGIN
// increment the counter
OUTER_SET counter+=1
// get the current state of the tape (0=blank)
ACTION_IF VARIABLE_IS_SET $turing_tape("%pointer%") BEGIN
OUTER_SET tape=$turing_tape("%pointer%")
END ELSE BEGIN
OUTER_SET tape=0
END
// run the machine
LAF "%machine%" INT_VAR tape STR_VAR state RET state mark_tape move END
// mark the tape
OUTER_SET $turing_tape("%pointer%")=mark_tape
// move the pointer
ACTION_MATCH "%move%" WITH
L BEGIN
OUTER_SET pointer +=1
END
R BEGIN
OUTER_SET pointer -=1
END
DEFAULT
FAIL "%move% is an illegal move output from Turing machine %machine%"
END
// display the tape and machine
ACTION_IF display_steps BEGIN
OUTER_SPRINT display ""
ACTION_SORT_ARRAY_INDICES turing_tape NUMERICALLY
ACTION_PHP_EACH turing_tape AS ind=>data BEGIN
OUTER_SPRINT display "%display%%data%"
END
PRINT "Step %counter%: Machine state: %state%; Tape state: %display%"
END
END
PRINT "Turing machine %machine%, with input %initial_tape%, halted after %counter% steps"
ENDYou use it like this:
LAF turing_machine INT_VAR display_steps=1 STR_VAR machine=my_machine END
'my_machine' is an action function encoding the machine's lookup table. Here's an example:
SpoilerDEFINE_ACTION_FUNCTION busy_beaver
INT_VAR tape=0
STR_VAR state=""
RET state
mark_tape
move
BEGIN
ACTION_MATCH "%state%" WITH
A BEGIN
OUTER_SET mark_tape=1
ACTION_IF tape=0 BEGIN
OUTER_SPRINT state B
OUTER_SPRINT move R
END ELSE BEGIN
OUTER_SPRINT state C
OUTER_SPRINT move L
END
END
B BEGIN
OUTER_SET mark_tape=1
ACTION_IF tape=0 BEGIN
OUTER_SPRINT state A
OUTER_SPRINT move L
END ELSE BEGIN
OUTER_SPRINT state B
OUTER_SPRINT move R
END
END
C BEGIN
OUTER_SET mark_tape=1
ACTION_IF tape=0 BEGIN
OUTER_SPRINT state B
OUTER_SPRINT move L
END ELSE BEGIN
OUTER_SPRINT state HALT
OUTER_SPRINT move R
END
END
DEFAULT
FAIL "%state% is an illegal internal state for busy_beaver"
END
END -
8 hours ago, Taylan said:
@kjeron Why not use SNDSLOT.IDS when it tells me which symbolic name corresponds to which integer index? No need to create one's own mappings. A sound set can define a WAV file for BATTLE_CRY1, SELECT_COMMON1, etc., and it will be automatically translated to the correct integer index based on the SNDSLOT.IDS of the game for which you're installing the sound set.
The issue is that the game engine (mostly) doesn't care what the symbolic names are. Take class.ids - it assigns a numeric value to each class, so that class 1 is labeled MAGE and so forth, but the engine (mostly) doesn't store or manipulate the symbolic names, only the numeric values. If you changed 'MAGE' to 'WIZARD' in class.ids, it would (mostly) leave the game unaffected.
(The 'mostly' caveat is because dialog files store their fragments of script uncompiled and compile it at run-time. So if there's a trigger in a dialog that checks if you're a mage, that change will confuse it.)
So if you change the label on sndslot 9 (currently BATTLE_CRY1) to SELECT_COMMON1, it won't make any difference to how the sound in slot 9 is used by the engine; it'll just mean it's labelled misleadingly. More seriously, if IWDEE uses BATTLECRY1 rather than BATTLE_CRY1, you still want your first battle-cry to be put in that slot.
Usually the various EE games are consistent across their ids files so that you can write multi-game code that refers to the ids symbols, at least if we're talking about BG2EE, BGEE, and IWDEE, all of which use the same engine. But there are exceptions, and I don't have much experience modding PSTEE, which has a different version of the engine. (My code above was to make a general point about WEIDU capabilities, not actually to thrash out what a working soundset program would be.) My advice here would probably be to standardize on the BG2EE version of sndslot.ids and just read the symbolic names in from a local copy in your mod folder rather than relying on the in-game version. In WEIDU I'd just read them into an array; I assume you can do something similar in Python (which I think is probably Turing-complete).
-
I'll stop after this, but here's a direct implementation of Taylan's design spec, in WEIDU rather than Python (again helping myself to a couple of auxiliary functions):
SpoilerDEFINE_ACTION_FUNCTION add_soundset
STR_VAR path=""
BEGIN// # Initialize our theoretical WeiDU library
// # This would do some magic to find the game files and such
INCLUDE "%MOD_FOLDER%/lib/sfo_lite.tph"// # Define mapping from human-readable sound IDs to game-specific integers
// no need: they're in sndslot.ids and WEIDU can read them directly// # Read the definitions for the sound set
ACTION_FOR_EACH category IN config sounds subs BEGIN
LAF parse_ini STR_VAR file="%path%/definitions.txt" category RET_ARRAY "%category%"=ini_array END
ENDOUTER_SPRINT name $config("name")
// # Copy the WAV files to where they belong
ACTION_PHP_EACH sounds AS k=>file BEGIN
COPY "%path%/%file%" override
END// # In this dictionary we will save mappings from WAV file name to string reference
ACTION_CLEAR_ARRAY strRefs// # Open the TLK file for our language
// no need, WEIDU opened it automaticallyACTION_PHP_EACH subs AS wav=>string BEGIN
// # Add the string to the game, receiving its numeric ref
// # Remember what WAV file name it belongs to
OUTER_PATCH_SAVE resref "%wav%" BEGIN REPLACE_TEXTUALLY "\..*" "" END // strip the .wav
OUTER_SET $strRefs("%wav%")=RESOLVE_STR_REF("%string%" ["%resref%"])
END// # Save the modified TLK file
// no need to do this in WEIDU// # Let's say the function parse2DA gives us a "2DA object"
COPY_EXISTING "charsnd.2da" override// # We will build up a new column to add to the 2DA
LPF add_blank_column STR_VAR header="%name%" entry="-1" END// # The 2DA object lets us get the rows via the rows property
// # And each row in turn has a cols property
// WEIDU does this slightly differently
COUNT_2DA_COLS colcount
COUNT_2DA_ROWS colcount rowcount
FOR (row=0;row<rowcount;++row) BEGIN
// # The sound's game-specific integer id is in the first column
READ_2DA_ENTRY row 0 colcount intId
// # Get the human-readable sound ID for that integer
LOOKUP_IDS_SYMBOL_OF_INT soundId sndslots intId
// # Get the WAV file name for that sound ID
SPRINT filename $sounds("%soundId%")
// # Get the string ref for that WAV file name
strRef = $strRefs("%filename%")
// # Add that to the column we're building
SET_2DA_ENTRY row (colcount - 1) colcount "%strRef%"
END
// # The function .addColumn takes a column title and the list of values for it
// we don't need this in WEIDU: we've been working directly with the file// # Install the modified 2DA file into the game directory
// That's happening automatically
PRETTY_PRINT_2DAEND
-
(EDIT: actually, skip this one, it's overcomplicating things.)
-
I feel the need to defend the honor of WEIDU.
Here's how I'd code this task in WEIDU, assuming exactly the input format for descriptions.txt in Taylan's post:
SpoilerDEFINE_ACTION_FUNCTION install_custom_soundset
STR_VAR soundset_path=""
soundset_definitions="definitions.txt"
file_path="%soundset_path%" // default to same location unless overwritten
BEGIN// parse the definitions
LAF parse_ini STR_VAR file="%soundset_path%/%soundset_definitions%" RET_ARRAY ini_array END
// copy over the files, and get an array of tlk entries to add to the table
ACTION_PHP_EACH ini_array AS k=>v BEGIN
ACTION_IF FILE_EXISTS "%file_path%/%v%" BEGIN
//install it
COPY "%file_path%/%v%" "override"
// get its non-suffix name
OUTER_PATCH_SAVE resref "%v%" BEGIN
REPLACE_TEXTUALLY EXACT_MATCH ".wav" ""
END
// get its associated text line, if any
ACTION_IF VARIABLE_IS_SET $ini_array("%v%") BEGIN
OUTER_SPRINT text_line $ini_array("%v%")
END ELSE BEGIN
OUTER_SPRINT text_line ""
END
// add to dialog.tlk
OUTER_SET strref=RESOLVE_STR_REF ("%text_line%" [%resref%])
// get the number for the command type
OUTER_SET code=IDS_OF_SYMBOL (sndslot "%k%")
OUTER_SET $soundset_write_array("%code%")=strref
END
END// add the entries
LAF add_blank_column STR_VAR 2da="charsnd.2da" header="%ini_array_name%" entry="-1" END
COPY_EXISTING "charsnd.2da" override
COUNT_2DA_COLS colcount
FOR (row=0;row<rowcount;++row) BEGIN
READ_2DA_ENTRY row 0 colcount row_number
PATCH_IF VARIABLE_IS_SET $soundset_write_array("%row_number%") BEGIN
v=$soundset_write_array("%row_number%")
SET_2DA_ENTRY row (colcount - 1) colcount v
END
END
BUT_ONLYEND
It appeals to a couple of subsidiary functions which I haven't defined; they'd be about 5-10 lines long each, I think. It took about 20 minutes to code, and it's about the same length as Taylan's Python script (and without appealing to a hypothetical library of weidu functions). The syntax is a little more cumbersome than python, to be sure.
WEIDU isn't perfect, but it's not just nominally Turing-complete; it's a reasonably effective programming language, even if 95% of mods don't use it that way. Would it be nice to have object-orientation, anonymous functions, more sophisticated handling of arrays as values, or a less idiosyncratic syntax? Sure. But it's way more powerful and flexible than it gets credit for.
-
@Angel: the only caveat I should give is that I have tattered shards of my own rewrite locally, so might not be able to incorporate third-party fixes very directly. (This is what happened for v31/v32 of SCS: CamDawg put together v31; v32 was built on v30 code with some manual incorporation of things from v31.)
-
I don't at all object. Feel free!
(Not basically around right now, too busy in real life.)
-
Yes. (It reflects the fact that the party are teleported in without warning, so it's implausible for the chess pieces to prebuff.)
This is externalized to stratagems\mage\override\[bg1/bg2]\boolean.2da. Setting the Boolean DoNotPrebuff turns off buffing. You'll see that in BG1 it applies to the chess pieces, to a couple of dopplegangers, to Silke in Beregost, and (iirc) to a couple of adventurers you can meet abruptly in Baldur's Gate.
-
It's because the mod isn't updated to WEIDU v247 yet.
-
Please do advertise, especially since this version seems to be glitchy (and I don't think there are reports of yours being).
-
Do many mods have translated READMEs? I would have thought that would be pretty problematic, for exactly the reason you give: they won't generally stay up-to-date.
-
I don't have anything to add to subtledoctor's sensible comment. (I have no real experience with MacOS.)
-
The icon trick was the only way I found to display a subrace. You can disguise it as a clone of an icon the creature ought already to have (e.g. magic resistance) if you also give them immunity to the original icon.
-
Liches don't have any specific immunity to False Dawn or Sunray. But they do often have resistance to fire damage (False Dawn) or magic damage (Sunray) due to their buffs, so I think it's probably that.
-
Don't overestimate SCS's AI. It's not clever enough to do a relative-armor check on spellcasters. Mostly it's working with a class-based priority list: if for the particular attack we're dealing with that priority list has cleric>bard, clerics will be prioritized.
If you think that's anomalous, and it would be better to do bard>cleric, I can tweak it. (Sometimes, e.g. when we're explicitly targeting mages, it's that way round already.)
-
Priests are sometimes prioritized over bards, so that might be part of it. I don't think it can be a mod conflict - this is a pure AI issue and SCS' AI is pretty much a destructive overwrite of the AI and wouldn't be affected by other mods.
apply spell upon unequipping item?
in Modding Q&A
Posted
I think that approach will cause trouble:
(i) you'll have to hardcode character abilities into the item, which is compatibility-unfriendly
(ii) taking the object off and back on again will recharge the ability.
My immediate thought is to get the item to set a spellstate. Then edit the spell to block it, and display a 'this power can't be used while wearing blah' message, when the spellstate is set.