Giant Frog swallow

Hello all,
Wondering if any script gurus could help me out with a script idea I have for the campaign I’m making?

Basically have a giant frog that can “swallow” a player or roster member (maybe teleport them to somewhere unseen in the area while they take acid damage slowly, with a % chance to get “released?” each round. Also, If players (not inside the frog) hit the frog, chance to release their teammate, as well?

  • or some creative variation of the above…

Now I think about it, it sounds pretty complicated. Thought I would throw it out there though.
Peace to you.

I could try and make something, but I know that @kevL_s or @Akhacha would probably do it a whole lot better. For them this wouldn’t be that hard, I believe.

When is the swallowing to take place? During a fight, a conversation or a trigger? It would be good to know…

So…here’s a start, I guess. Two scripts. The latter to be placed on OnDamage of the frog. I’m sure the other script gurus can make this way better than me, but perhaps…try it out? I haven’t tested this, and I still only know basic scripting, so there are bound to be mistakes in there.

void PseudoHeartbeat(object oCompanion, object oFrog)
{

	if(!GetLocalInt(oFrog,"swallow")) return;

	ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(3, DAMAGE_TYPE_ACID), oCompanion);
		
	int dice = d6();
		
	if(dice == 6)
	{
	
		SetLocalInt(oFrog,"swallow",FALSE);	
	
	}
	
	DelayCommand(6.0f, PseudoHeartbeat(oCompanion,oFrog));
}



void main()
{
    object oPC = GetFirstPC();
	object oFrog = GetObjectByTag("frogtag");
	
	if(!GetLocalInt(oFrog,"swallow")) return;
	
	object oCompanion = GetObjectByTag("companiontag");

    object oDestCompanion = GetWaypointByTag("waypointtag");
	
   	if(GetFactionEqual(oPC,oCompanion))
	{
           
       RemoveRosterMemberFromParty("companiontag", oPC, FALSE);

       AssignCommand(oCompanion, ClearAllActions());
       AssignCommand(oCompanion, JumpToObject(oDestCompanion));
	   
	   SetLocalInt(oFrog,"swallow",TRUE);
	   
	   PseudoHeartbeat(oCompanion,oFrog);

	}
	
	
           
  
}

The OnDamage script of the frog:

void main()
{

	object oFrog = GetObjectByTag("frogtag");
	
	if(!GetLocalInt(oFrog,"swallow")) return;
	
	object oCompanion = GetObjectByTag("companiontag");
	
	int dice = d6();
		
	if(dice == 6)
	{
	
 		AssignCommand(oCompanion, JumpToObject(oFrog));
           
	}
  
}
1 Like

Project Q IV | The Neverwinter Vault has giant frog swallowing. Its coded for NWN1 but it should work in NWN2.

1 Like

Rather than teleport them, you can make them script hidden.

Try something like this for the devour ability itself (special ability, or on hit, or whatever you like):

void ExpelDigestee()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (!GetIsObjectValid(oDigestee))
		return;
	effect eEffect = GetFirstEffect(oDigestee);
	while (GetIsEffectValid(eEffect))
	{
		if (GetEffectType(eEffect) == EFFECT_TYPE_CUTSCENE_PARALYZE)
		{
			RemoveEffect(oDigestee, eEffect);
			eEffect = GetFirstEffect(oDigestee);
		}
		else
			eEffect = GetNextEffect(oDigestee);
	}
	SetScriptHidden(oDigestee, FALSE);
	DeleteLocalObject(OBJECT_SELF, "oDigestee");
}

void DoAcidDamage()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (!GetIsObjectValid(oDigestee))
		return;
	if (!GetIsDead(oDigestee))
	{
		effect eAcidDamage = EffectDamage(3, DAMAGE_TYPE_ACID); // Make sure to edit this for desired damage
		ApplyEffectToObject(DURATION_TYPE_INSTANT, eAcidDamage, oDigestee, 0.0);
		if (!GetIsDead(oDigestee))
			DelayCommand(6.0, DoAcidDamage());
		else
			ExpelDigestee();
	}
	else
	{
		ExpelDigestee();
	}
}

void main()
{
	object oTarget = GetSpellTargetObject();
	if (!GetIsObjectValid(oTarget))
		return;
	if (GetIsObjectValid(GetLocalObject(OBJECT_SELF, "oDigestee")))
		return;	// Can't devour another person if belly is already full!

	SetLocalObject(OBJECT_SELF, "oDigestee", oTarget);
	effect eParalyse = EffectCutsceneParalyze();
	effect eIcon = EffectEffectIcon(16);
	eParalyse = EffectLinkEffects(eIcon, eParalyse);
	ApplyEffectToObject(DURATION_TYPE_PERMANENT, eParalyse, oTarget, 0.0);
	SetScriptHidden(oTarget, TRUE);
	DelayCommand(6.0, DoAcidDamage());
}

And something like this for the creature’s on damaged script:

void ExpelDigestee()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (!GetIsObjectValid(oDigestee))
		return;
	effect eEffect = GetFirstEffect(oDigestee);
	while (GetIsEffectValid(eEffect))
	{
		if (GetEffectType(eEffect) == EFFECT_TYPE_CUTSCENE_PARALYZE)
		{
			RemoveEffect(oDigestee, eEffect);
			eEffect = GetFirstEffect(oDigestee);
		}
		else
			eEffect = GetNextEffect(oDigestee);
	}
	SetScriptHidden(oDigestee, FALSE);
	DeleteLocalObject(OBJECT_SELF, "oDigestee");
}

void main()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (GetIsObjectValid(oDigestee))
	{
		if (Random(10) == 0)	// Set your desired chance of expelling digested member here
			ExpelDigestee();
	}
}

And for some redundancy, because you absolutely won’t want to leave a character as script hidden (shouldn’t happen with the safeguards in place above, but “shouldn’t” and “won’t” happen are not the same thing!), make sure the creature’s on death script has something similar to the on damaged script too, just without the random portion of course.

Edit: in fact I’d probably do some extra checks in the on death script, such as:

void ExpelDigestee()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (!GetIsObjectValid(oDigestee))
		return;
	effect eEffect = GetFirstEffect(oDigestee);
	while (GetIsEffectValid(eEffect))
	{
		if (GetEffectType(eEffect) == EFFECT_TYPE_CUTSCENE_PARALYZE)
		{
			RemoveEffect(oDigestee, eEffect);
			eEffect = GetFirstEffect(oDigestee);
		}
		else
			eEffect = GetNextEffect(oDigestee);
	}
	SetScriptHidden(oDigestee, FALSE);
	DeleteLocalObject(OBJECT_SELF, "oDigestee");
}

void main()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (GetIsObjectValid(oDigestee))
			ExpelDigestee();

	object oPC = GetFirstPC();
	object oParty = GetFirstFactionMember(oPC, FALSE);

	while (GetIsObjectValid(oParty))
	{
		if (GetScriptHidden(oParty))
			SetScriptHidden(oParty, FALSE);
		effect eEffect = GetFirstEffect(oParty);
		while (GetIsEffectValid(eEffect))
		{
			if (GetEffectType(eEffect) == EFFECT_TYPE_CUTSCENE_PARALYZE)
			{
				RemoveEffect(oParty, eEffect);
				eEffect = GetFirstEffect(oParty);
			}
			else
				eEffect = GetNextEffect(oParty);
		}
		oParty = GetNextFactionMember(oPC, FALSE);
	}
}

There’s a few things you may want to add, such as notice text to indicate what is happening, because that is probably not going to be obvious to players, but it seems functional enough from a quick test.

1 Like

Ahh genius! I wouldn’t have considered ‘script hidden’. Thanks Akhacha and Andgalf for your responses. Just checked this post now before bed, but I’ll give your script a go tomorrow Akhacha and post back here then. Much appreciated.

Thanks Kaldor! I recall I tested your module years ago when I started an old campaign that never came to fruition. It was handy for helping me setup my villagers day/night living, if i recall. Helped me a ton back then.

The 9 hours spent yesterday, was mostly figuring out hak/override/campaign folders and .2da entries. Actually most of it was spent trying to get PJ placeables to work :slight_smile:

1 Like

@Akhacha - Will scripting affect a creature that’s script hidden? Just curious. Maybe it does…I mean, you begin to apply the acid damage after it’s script hidden, that’s why I ask.

If scripting couldn’t affect a creature that was script hidden, we’d have an awfully hard time removing the script hidden status!

But yes, it does work, even if you apply it after you set them to be script hidden.

1 Like

Hi again. Having issues with the placement of your first script. There’s no on hit category in nwn2 to place a script in.
Tried putting the script in all places it could go, but none seem to work?
I also tried adding creature variables to the frog for a custom ai variable string, using the script name. I’m clueless, sorry.

First, make a weapon you want to use. Under the properties tab, go to “Item Properties” and add the “On Hit Cast Spell: Unique Power” property.

Next, you need to name the script based on the tag of your weapon as follows: i_[ITEMTAG]_hc

So for example, if your weapon has the tag “frogbite”, name it “i_frogbite_hc”.

Hi Akhacha, got it working! So cool!
Tested it out some and it works nicely, thank you.
I did notice however, that if I fight it solo (without party members), as soon as my PC gets swallowed, the frog itself seems to go scripthidden. I’m not sure if that’s because “technically” my PC can’t see anything, once it is scripthidden? It works nicely in a party though - which is when it will be encountered in the campaign.

Could you please add a relevant floating text over frog, to describe the event that has occurred, because as you said players may not know what’s going on.

Note for others wanting to use it: I found making a creature item (must be creature item) and placed that item in the creatures hide/skin tab -following Akhacha’s script naming advice just above.

I think if you just add this line of code after the ScriptHidden(oTarget,TRUE); it would do what you want.

object oFrog = GetObjectByTag(frogtag);
AssignCommand(oFrog,SpeakString(The frog swallows your companion.));

The frog disappears because it’s undetectable, you can tell the difference in that it fades out whereas the character disappears abruptly.

Anyway, try the following script:

int IsPartyDead()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	object oParty = GetFirstFactionMember(oDigestee, FALSE);
	while (GetIsObjectValid(oParty))
	{
		if (oParty != oDigestee && !GetIsDead(oParty))
			return FALSE;
		oParty = GetNextFactionMember(oDigestee, FALSE);
	}
	return TRUE;
}

void ExpelDigestee()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (!GetIsObjectValid(oDigestee))
		return;
	effect eEffect = GetFirstEffect(oDigestee);
	while (GetIsEffectValid(eEffect))
	{
		if (GetEffectType(eEffect) == EFFECT_TYPE_CUTSCENE_PARALYZE)
		{
			RemoveEffect(oDigestee, eEffect);
			eEffect = GetFirstEffect(oDigestee);
		}
		else
			eEffect = GetNextEffect(oDigestee);
	}
	SetScriptHidden(oDigestee, FALSE);
	DeleteLocalObject(OBJECT_SELF, "oDigestee");
}

void DoAcidDamage()
{
	object oDigestee = GetLocalObject(OBJECT_SELF, "oDigestee");
	if (!GetIsObjectValid(oDigestee))
		return;
	if (!GetIsDead(oDigestee))
	{
		if (IsPartyDead())
		{
			SetScriptHidden(oDigestee, FALSE);
			effect eDeath = EffectDeath(FALSE, TRUE, TRUE);
			ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oDigestee, 0.0);
		}
		else
		{
			effect eAcidDamage = EffectDamage(3, DAMAGE_TYPE_ACID); // Make sure to edit this for desired damage
			ApplyEffectToObject(DURATION_TYPE_INSTANT, eAcidDamage, oDigestee, 0.0);
		}
		if (!GetIsDead(oDigestee))
			DelayCommand(6.0, DoAcidDamage());
		else
			ExpelDigestee();
	}
	else
	{
		ExpelDigestee();
	}
}

void main()
{
	object oTarget = GetSpellTargetObject();
	if (!GetIsObjectValid(oTarget))
		return;
	if (GetIsObjectValid(GetLocalObject(OBJECT_SELF, "oDigestee")))
		return;	// Can't devour another person if belly is already full!

	SetLocalObject(OBJECT_SELF, "oDigestee", oTarget);
	effect eParalyse = EffectCutsceneParalyze();
	effect eIcon = EffectEffectIcon(16);
	eParalyse = EffectLinkEffects(eIcon, eParalyse);
	ApplyEffectToObject(DURATION_TYPE_PERMANENT, eParalyse, oTarget, 0.0);
	SetScriptHidden(oTarget, TRUE);
	SetNoticeText(GetFirstPC(), GetName(oTarget) + " was eaten by " + GetName(OBJECT_SELF) + "!");
	DelayCommand(6.0, DoAcidDamage());
}

You can also use FloatingTextStringOnCreature() if you prefer, I personally like this one though since it’s harder to miss. But that’s personal preference.

I also added a check to see if rest of party is dead since there’s a chance that the eaten character has enough acid resistance or passive regeneration that you could end up getting stuck forever otherwise.

According to some notes I have, this function doesn’t work for NPCs.

It works if you set the target to a PC, or, as long as you don’t set BroadcastToFaction to FALSE, a roster member.

So something like:

FloatingTextStringOnCreature("Message here", GetFirstPC());
FloatingTextStringOnCreature("Message here", oTarget());

would work fine in the above script.

It’s definitely a bit buggy though, from the description you’d expect setting BroadcastToFaction to FALSE to expand its reach, but it seems to restrict it further instead, making it not show up if used on roster members.

Tested the above and works a treat. I may test some more on creating a “monster weapon”, because putting it on the hide works and all, but my ranger who shot it from quite a distance away, got swallowed hehe. I tried a “creature bludgeoning weapon” on-hit cast spell item earlier, but it only gave the acid and bludgeoning damage and no swallowing of a player character.

Thanks for assisting! I was very hesitant to ever ask for scripts on a forum, but I am pleased to see it was successful and efficient. Thanks.

Ah, good to know! I did see you used SetNoticeText in your script. Haven’t used that function before. Will try to remember it. I do think my suggestion with SpeakString would also work though.

You should never be hesitant about that. I have had huge help from for example @kevL_s , @travus , @Aqvilinus and others throughout the years with scripting. Everyone are always very helpful around here! As long as you’re humble and not demand stuff, but ask kindly for assistance, most script gurus here are very willing to help. Nowadays I can at least conjure up basic scripts thanks to those guys and many more.
And it’s great to see a relative newcomer like @Akhacha here as he’s very skilled too.

1 Like

It seems to me that the script might need an adjustment so that someone who has attacked from beyond a certain distance can’t be swallowed because they’re considered out of range. Either that, or there needs to be some kind of effect to indicate the swallowing is a ranged attack (like it was the frog’s tongue catching the ranged attacker)

2 Likes

I have since noticed, that on the item properties of a creatures “weapon”/claws etc, there is an option in there for “on_hit_special_effect” or something like that. I think that might be what Akhacha was eluding to. I misunderstood them and assumed they meant the properties of the creature, not the item.

@Akhacha:> First, make a weapon you want to use. Under the properties tab, go to “Item Properties” and add the “On Hit Cast Spell: Unique Power” property.

@Melkior_Wiseman: that should solve the ranged swallow issue.

1 Like