Gun Shooting Example

Does anyone know of a good, basic gun shooting example in t3? I’ve tried writing a ‘shoot’ verb, but not sure the best way to go about, checking that the user can shoot at the time, adjusting the target to die etc, and am not really sure what such a scenario would look like in tads3 so I’m not sure where to begin.

Thanks so much!

Seems to me I tried something like this at one time. The starting point in the design would probably be to list the commands that you want the player to be able to use. For instance, ‘shoot revolver at Bob’ is entirely equivalent to ‘shoot Bob with revolver’ (or, for that matter, ‘shoot at Bob with revolver’ or plain old ‘shoot at Bob’ or ‘shoot Bob’ when the player is holding the revolver). So the ShootAt action is quite different grammatically from the ShootWith action. But if you work through the possibilities carefully, it should all work.

ReplaceAction is your friend.

Thanks so much!

So on the object end - it seems it would be ideal to define what happens to Bob when he is shot within Bob. - maybe even just a variable value etc.
What would the code look like in the objects - where the shoot with verb is handled?
Hopefully I worded that so it makes sense :confused:

Thanks!

Right – depending on what you want to happen. Let’s assume for the moment that Bob is only wounded, not dead. After defining the ShootWith and ShootAt actions, the Bob object might include some code like this (untested):

isWounded = nil dobjfor(ShootWith) { verify() { logical; } check() { if (isWounded) { failcheck( '<q>Hey, guy! You already shot me once! Can\'t you see I\'m bleeding?</q> '); } action() { isWounded = true; "<q>OW!</q> Bob shouts, as blood spurts from his knee. "; } } iobjFor(ShootAt) { verify() { logical; } check() { if (gDobj != revolver) failcheck ('<q>That ain\'t gonna hurt me none!</q> Bob says with a hearty laugh. '); } action () { replaceAction(ShootWith, self, gDobj); } }

If shooting Bob kills him, the usual way to handle it would be to whisk the bob object offstage silently and replace it with the deadBob object (which would be just a Thing, not an Actor).

Thanks so much! I’ll use that is a starting point. - we’ll see how I do hehe - If I get it to work well I’ll post what I went with.

Ok so I’m STILL working on this. I did some work in other areas of the game but have recently added the first ‘shootable’ object to the game. Using the code below I am able to show the illogical text for anything where ‘canShoot’ is nil - but when this verification is successful I never get the action to fire, it just says nothing obvious happens. I’m overlooking something maybe someone will see it at a glance. My verb code:

DefineTAction(Shoot);
VerbRule(Shoot)
 ('shoot') singleDobj
 : ShootAction
 verbPhrase = 'shoot (what)'
;
modify Thing
 dobjFor(Shoot)
 {
    verify() 
    {
        if ([canShoot] != true)
        {
            illogical('\bShooting this would do nothing more than cause damage to it.' + [canShoot] + '\b');
        }
    }
    action() 
    {
        'cool!';
    }
 }
;

My shootable object code:

EngineRoomLeftDoor_Outer: TravelWithMessage, Door 'left door' 'Left Door'
{
    location = Hold01Aft
    noun = 'door'
    adjective = 'left' 'aft'
    sightPresence = true
    isListed = nil
    isPlural = nil
    initiallyOpen = true
    initialDesc = 0
    masterObject = EngineRoomLeftDoor
    canShoot = true

    travelDesc()
    {
        cls();

        "\b\r\n
You enter the engine room door.
        ";
    }

    desc()
    {
        "
You examine the door that leads back into the engine room. It is of a solid metal construction
with reinforced hinges and heavy duty bolt locks.
        ";
    }
    
    dobjFor(Shoot)
    {
        verify() { logical; }
        action()
        {
            'Boom!!';
        }
    }
}

Thanks SO much!

Eeeesh - looks like it’s simply the single quotes in my action() so … carry on, nothing to see here

Have you figured all this out yet? I just implemented something very similar in my game, and I’ve got code for differentiating between >shoot gun, and >shoot bob, and all sorts of other combinations like:

Shoot gun at Bob
Shoot at Bob
shoot Bob with gun
shoot at Bob with gun

Along with handling for what goes in the gun (in your case, probably a bullet. In my case it’s a blowgun so I’m using a clay pellet) so the player can do things like

Put pellet in gun
Load gun
Shoot pellet at Bob

etc.

Let me know if this would be useful to you, and if so, I’ll post it.

–Bob

I did, thanks! So far I’m just checking the gun the player is shooting - and I’m certain the verb flexibility will need to be expanded, but at this point in development it is working great!

If you wouldn’t mind posting what you have, however, that might be useful for other weapons/devices the player might encounter. Being a scifi game, there will most likely be plenty of need for ‘device does X because it has Y chip in it’ or ‘is in Z mode’ etc.

Thanks!

Sorry for the delay in responding to this, but I have now gathered all the special code I wrote for gun handling into one spot. I hope it turns out to be useful. The goal is to handle the difficulties that English presents in understanding the different syntaxes used for shooting something. (e.g., >Shoot gun and >Shoot target). I believe this code deals successfully with inputs like:

shoot gun
Shoot gun at target
Shoot target with gun
Shoot at target with gun
Shoot at target
Shoot bullet at target (etc)
Fire gun (etc)
Load gun
For this scenario I have created a blowpipe, with this the equivalent of a gun, and a pellet, with is the equivalent of a bullet.

A few caveats: I am still quite a novice at TADS (which you can see from my inelegant coding style) so there are probably more efficient ways to do these things. Also, my game hasn’t been tested yet, so although this code seems to work for me, it hasn’t been given a good working-over, so proceed with caution!

Best of luck,

–Bob


/***********************
OBJECT HANDLING
***********************/

th_blowpipe: Container
{
    name = 'blowpipe'
    vocabWords = 'bamboo blow blowpipe blowpipe gun/pipe/tube'
    location = rm_target
    isListedInContents = (moved) //So that it won't be listed in the contents of the room until after you have moved it.
    dobjFor(Examine) {
        action() {
            "It's a bamboo tube that is at least 8 feet long. ";
        }
    }
    dobjFor(Shoot) { //The Player's input is >Shoot gun (Not >shoot foo, or >shoot gun at foo)
        action () {  //In other words the player has typed shoot gun, but not specified what he wants to shoot it at.  Ask him.
                askForIobj(ShootWeaponAt); //This sends us over to ShootWeaponAt from here on.
        }
    }
    dobjFor(ShootWeaponAt) { //The Player's input is >Shoot gun at foo, or is piped here from >Shoot gun
        action () {
            if (!th_blowpipe.isIn(me)) {
                "You'd have to be holding the blowpipe to fire it. ";
            }
            else if (!th_pellet.isIn(th_blowpipe)) {
                "The blowpipe isn't loaded. ";
            }        
            else if (gIobj == th_target) {
                "You fire the pellet at the target and hit it. The pellet falls to the ground and disintegrates. ";
                th_pellet.moveInto(nil);
            }
            else { 
                say ('The pellet strikes {the iobj/him} then falls to the ground and disintegrates. ');
                th_pellet.moveInto(nil);
            }
        }
    }
    dobjFor(Blow) { //The Player's input is >Blow gun 
        action () {  //In other words the player has typed >shoot gun, but not specified what he wants to shoot it at.  Ask him.
                askForIobj(ShootWeaponAt); //This sends us over to ShootWeaponAt from here on.
        }
    }
    dobjFor(BlowAt) {
        action () {
            replaceAction (ShootWeaponAt, th_blowpipe, gIobj);
        }        
    }
    dobjFor(Load) {
        action () {
            if (th_pellet.isIn(getOutermostRoom)) {
                replaceAction (PutIn, th_pellet, th_blowpipe);
            }
            else {
                "You don't have anything to put in the blowpipe. ";
            }
        }
    }
    dobjFor(LoadWith) {
        action() {
            if (gIobj == th_pellet) {
                replaceAction (Load, th_blowpipe);
            }
            else {
                say ('{The iobj/him} {does}n\'t fit inside the blowpipe. ');
            }
        }
    }
    dobjFor (Break) {
        verify () {}
        action () {
            "The blowpipe is made of stout bamboo. You can't break it. ";
        }
    }
    iobjFor(ShootWith) {
        action () {
            replaceAction (ShootWeaponAt, th_blowpipe, gDobj);
        }
    }
    iobjFor(PutIn) {
        action {
            if (gDobj == th_pellet) {
                "You put the pellet into the blowpipe. ";
                inherited;
            }
            else {
                "That won't fit inside the blowpipe. ";
            }
        }
    }
}

th_pellet: Thing
{
    name = 'pellet' 
    vocabWords = 'small round clay pellet'
    location = nil
    dobjFor(Examine) {
        action() {
            "It's a small round pellet made of clay. ";
        }
    }
    dobjFor(ShootWeaponAt) { //The Player's input is >Shoot pellet at foo
        action () {
            replaceAction (ShootWeaponAt, th_blowpipe, gIobj);

        }
    }
    dobjFor(Blow) { //The Player's input is >Blow pellet
        action () {  //In other words the player has typed blow pellet, but not specified what he wants to shoot it at.  Ask him.
                askForIobj(ShootWeaponAt); //This sends us over to ShootWeaponAt from here on.
        }
    }
    dobjFor(BlowAt) {
        action () {
            replaceAction (ShootWeaponAt, th_blowpipe, gIobj);
        }        
    }
}

th_target: Fixture
{
    name = 'target' 
    vocabWords = 'target'
    location = rm_target
    dobjFor(Examine) {
        action() {
            "It's like an archery target, with concentric rings and a bull's eye. ";
        }
    }    
}

/***********************
VERB HANDLING
***********************/

/***********************
BLOW
***********************/

DefineTAction(Blow);

VerbRule(Blow)
     ('blow' | 'blow' 'in' | 'blow' 'into' | 'blow' 'at' ) singleDobj
     : BlowAction
     verbPhrase = 'blow/blowing (what)'
;

modify Thing
    dobjFor(Blow) {
        action () { //Note that blowing into the blowpipe is handled in the blowpipe itself
            if (gDobj.ofKind(Person)) {
                "Hey! Let's keep things civil. ";
            }
            else {
                "That would be a waste of breath. ";
            }
        }
    }
;

/***********************
BLOW-AT
***********************/

DefineTIAction(BlowAt);
    
VerbRule(BlowAt)
    ('blow') singleDobj ('at') singleIobj
    : BlowAtAction
    verbPhrase = 'blow/blowing (what) (at what)'
    askIobjResponseProd = onSingleNoun
    askDobjResponseProd = onSingleNoun
;

modify Thing
    dobjFor(BlowAt) {
        action () { //Note that blowing into the blowpipe is handled in the blowpipe itself
                "Save your breath. You'll need it for the spectacular finale. ";
        }
    }
;

/***********************
LOAD
***********************/

DefineTAction(Load);

VerbRule(Load)
     ('load') singleDobj
     : LoadAction
     verbPhrase = 'load/loading (what)'
;

modify Thing
    dobjFor(Load) {
        action () {
            replaceAction (Take, gDobj);
        }
    }
;

/***********************
LOADWITH (LOAD GUN WITH PELLET)
***********************/

DefineTIAction(LoadWith)
    /* resolve the direct object first */
    resolveFirst = DirectObject

    /* limit 'all' for the indirect object to items in inventory */
    getAllIobj(actor, scopeList)
    {
        return scopeList.subset({x: x.isIn(actor)});
    }
;

VerbRule(LoadWith)
    'load' singleDobj 'with' singleIobj
    : LoadWithAction
    verbPhrase = 'load/loading (what) (with what)'
    omitIobjInDobjQuery = true  //TODO:  RAB, This and next two lines are stolen from "UnlockWith" and I don't know what they do
    askDobjResponseProd = singleNoun
    askIobjResponseProd = withSingleNoun
;

modify Thing
    dobjFor(LoadWith)
    {
        preCond = [touchObj]
    }
    iobjFor(LoadWith)
    {
        preCond = [objHeld]
    }
;

/***********************
SHOOT, SHOOT-WEAPON-AT, SHOOT-WITH
***********************/

DefineTAction(Shoot);
DefineTIAction(ShootWeaponAt);
DefineTIAction(ShootWith);

VerbRule(Shoot)
    ('shoot' | 'fire' | 'shoot' 'at' | 'fire' 'at' ) singleDobj
    : ShootAction
    verbPhrase = 'shoot/shooting (what)'
;

VerbRule(ShootWeaponAt)
    ('shoot' | 'fire') singleDobj ('at') singleIobj
    : ShootWeaponAtAction
    verbPhrase = 'shoot/shooting (what) (at what)'
    askIobjResponseProd = onSingleNoun
    askDobjResponseProd = onSingleNoun
;

VerbRule(ShootWith)
    ('shoot' | 'fire' |'shoot' 'at' | 'fire' 'at') singleDobj 'with' singleIobj
    : ShootWithAction
    verbPhrase = 'shoot/shooting (at what) (with what)'
    omitIobjInDobjQuery = true
    askDobjResponseProd = atSingleNoun
    askIobjResponseProd = withSingleNoun
;

modify Thing
    dobjFor(Shoot)
    {
        action() { //The player has typed >Shoot or >Shoot foo, where foo is something he wants to shoot at.
                    // If he had typed >Shoot gun, it would have been caught before this by the blowpipe handling.
            if (th_pellet.isIn(th_blowpipe)) {
                replaceAction (ShootWeaponAt, th_blowpipe, gDobj);  // If the player is has loaded the blowpipe, >Shoot foo should fire at the foo
                                                                    // This avoids the game asking him "What do you want to shoot the foo with, when
                                                                    // it is obvious that he is holding a loaded weapon.
            }
            else {
                askForIobj(ShootWith); 
            }
        }
    }
;

modify Thing    
    dobjFor(ShootWeaponAt)
    {
        action () {
            if (gDobj == th_pellet) {
                replaceAction (ShootWeaponAt, th_blowpipe, gIobj);  // In case this gets here as the result of an orphan from "What do you want
                                                                    // to shoot at foo with, and the player types "pellet."
            }
            else {
                say ('You can\'t shoot anything with {a dobj/him}. ');
            }
        }
    }
;

modify Thing    
    iobjFor(ShootWith)
    {
        action () {
            if (gIobj == th_pellet) {
                replaceAction (ShootWeaponAt, th_blowpipe, gDobj);  // In case this gets here as the result of an orphan from "What do you want
                                                                    // to shoot at foo with, and the player types "pellet."
            }
            else {
                say ('You can\'t shoot anything with {a iobj/him}. ');
            }
        }
    }
;