shithub: cstory

Download patch

ref: 593995d410b38d4987ca764da6e0a3b6cefb853b
parent: 528f77538790d8e66f691582e65fda3b5049f03c
author: Clownacy <Clownacy@users.noreply.github.com>
date: Tue Feb 5 13:49:03 EST 2019

Added more NPCs

That should be Sand Zone done.

--- a/src/NpcAct.h
+++ b/src/NpcAct.h
@@ -46,14 +46,20 @@
 void ActNpc041(NPCHAR *npc);
 void ActNpc042(NPCHAR *npc);
 void ActNpc043(NPCHAR *npc);
-
+void ActNpc044(NPCHAR *npc);
+void ActNpc045(NPCHAR *npc);
 void ActNpc046(NPCHAR *npc);
-
+void ActNpc047(NPCHAR *npc);
 void ActNpc048(NPCHAR *npc);
-
+void ActNpc049(NPCHAR *npc);
+void ActNpc050(NPCHAR *npc);
+void ActNpc051(NPCHAR *npc);
+void ActNpc052(NPCHAR *npc);
+void ActNpc053(NPCHAR *npc);
+void ActNpc054(NPCHAR *npc);
 void ActNpc055(NPCHAR *npc);
 void ActNpc056(NPCHAR *npc);
-
+void ActNpc057(NPCHAR *npc);
 void ActNpc058(NPCHAR *npc);
 void ActNpc059(NPCHAR *npc);
 void ActNpc060(NPCHAR *npc);
@@ -120,14 +126,29 @@
 void ActNpc121(NPCHAR *npc);
 void ActNpc122(NPCHAR *npc);
 void ActNpc123(NPCHAR *npc);
-
+void ActNpc124(NPCHAR *npc);
 void ActNpc125(NPCHAR *npc);
-
+void ActNpc126(NPCHAR *npc);
 void ActNpc127(NPCHAR *npc);
 void ActNpc128(NPCHAR *npc);
 void ActNpc129(NPCHAR *npc);
-
+void ActNpc130(NPCHAR *npc);
+void ActNpc131(NPCHAR *npc);
+void ActNpc132(NPCHAR *npc);
+void ActNpc133(NPCHAR *npc);
+void ActNpc134(NPCHAR *npc);
+void ActNpc135(NPCHAR *npc);
+void ActNpc136(NPCHAR *npc);
+void ActNpc137(NPCHAR *npc);
+void ActNpc138(NPCHAR *npc);
+void ActNpc139(NPCHAR *npc);
+void ActNpc140(NPCHAR *npc);
+void ActNpc141(NPCHAR *npc);
+void ActNpc142(NPCHAR *npc);
+void ActNpc143(NPCHAR *npc);
+void ActNpc144(NPCHAR *npc);
 void ActNpc145(NPCHAR *npc);
+void ActNpc146(NPCHAR *npc);
 
 void ActNpc150(NPCHAR *npc);
 void ActNpc151(NPCHAR *npc);
@@ -143,9 +164,13 @@
 
 void ActNpc278(NPCHAR *npc);
 
+void ActNpc292(NPCHAR *npc);
+
 void ActNpc298(NPCHAR *npc);
 void ActNpc299(NPCHAR *npc);
 void ActNpc300(NPCHAR *npc);
+
+void ActNpc302(NPCHAR *npc);
 
 void ActNpc355(NPCHAR *npc);
 
--- a/src/NpcAct040.cpp
+++ b/src/NpcAct040.cpp
@@ -9,6 +9,7 @@
 #include "Sound.h"
 #include "Back.h"
 #include "Triangle.h"
+#include "CommonDefines.h"
 
 //Santa
 void ActNpc040(NPCHAR *npc)
@@ -412,6 +413,254 @@
 		npc->rect = rcRight[0];
 }
 
+//Polish
+void ActNpc044(NPCHAR *npc)
+{
+	RECT rcRight[3];
+	RECT rcLeft[3];
+
+	rcRight[0] = {0, 0, 32, 32};
+	rcRight[1] = {32, 0, 64, 32};
+	rcRight[2] = {64, 0, 96, 32};
+
+	rcLeft[0] = {0, 0, 32, 32};
+	rcLeft[1] = {96, 0, 128, 32};
+	rcLeft[2] = {128, 0, 160, 32};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			// Fallthrough
+		case 1:
+			npc->ani_no = 0;
+
+			if (npc->direct == 0)
+				npc->act_no = 8;
+			else
+				npc->act_no = 2;
+			// Fallthrough
+		case 2:
+			npc->ym += 0x20;
+
+			if (npc->ym > 0 && npc->flag & 8)
+			{
+				npc->ym = -0x100;
+				npc->xm += 0x100;
+			}
+
+			if (npc->flag & 4)
+				npc->act_no = 3;
+
+			break;
+
+		case 3:
+			npc->xm += 0x20;
+
+			if (npc->xm > 0 && npc->flag & 4)
+			{
+				npc->xm = -0x100;
+				npc->ym -= 0x100;
+			}
+
+			if (npc->flag & 2)
+				npc->act_no = 4;
+
+			break;
+
+		case 4:
+			npc->ym -= 0x20;
+
+			if (npc->ym < 0 && npc->flag & 2)
+			{
+				npc->ym = 0x100;
+				npc->xm -= 0x100;
+			}
+
+			if (npc->flag & 1)
+				npc->act_no = 5;
+
+			break;
+
+		case 5:
+			npc->xm -= 0x20;
+
+			if (npc->xm < 0 && npc->flag & 1)
+			{
+				npc->xm = 0x100;
+				npc->ym += 0x100;
+			}
+
+			if (npc->flag & 8)
+				npc->act_no = 2;
+
+			break;
+
+		case 6:
+			npc->ym += 0x20;
+
+			if (npc->ym > 0 && npc->flag & 8)
+			{
+				npc->ym = -0x100;
+				npc->xm -= 0x100;
+			}
+
+			if (npc->flag & 1)
+				npc->act_no = 7;
+
+			break;
+
+		case 7:
+			npc->xm -= 0x20;
+
+			if (npc->xm < 0 && npc->flag & 1)
+			{
+				npc->xm = 0x100;
+				npc->ym -= 0x100;
+			}
+
+			if (npc->flag & 2)
+				npc->act_no = 8;
+
+			break;
+
+		case 8:
+			npc->ym -= 0x20;
+
+			if (npc->ym < 0 && npc->flag & 2)
+			{
+				npc->ym = 0x100;
+				npc->xm += 0x100;
+			}
+
+			if ( npc->flag & 4 )
+				npc->act_no = 9;
+
+			break;
+
+		case 9:
+			npc->xm += 0x20;
+
+			if (npc->xm > 0 && npc->flag & 4)
+			{
+				npc->xm = -0x100;
+				npc->ym += 0x100;
+			}
+
+			if (npc->flag & 8)
+				npc->act_no = 6;
+
+			break;
+	}
+
+	if (npc->life <= 100)
+	{
+		for (int i = 0; i < 10; ++i)
+			SetNpChar(45, npc->x, npc->y, 0, 0, 0, 0, 0x100);
+
+		SetDestroyNpChar(npc->x, npc->y, npc->view.back, 8);
+		PlaySoundObject(25, 1);
+		npc->cond = 0;
+	}
+
+	if (npc->xm > 0x200)
+		npc->xm = 0x200;
+	if (npc->xm < -0x200)
+		npc->xm = -0x200;
+
+	if (npc->ym > 0x200)
+		npc->ym = 0x200;
+	if (npc->ym < -0x200)
+		npc->ym = -0x200;
+
+	if (npc->shock)
+	{
+		npc->x += npc->xm / 2;
+		npc->y += npc->ym / 2;
+	}
+	else
+	{
+		npc->x += npc->xm;
+		npc->y += npc->ym;
+	}
+
+	if (npc->act_no >= 2 && npc->act_no <= 9 && ++npc->ani_no > 2)
+		npc->ani_no = 1;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Baby
+void ActNpc045(NPCHAR *npc)
+{
+	RECT rect[3];
+
+	rect[0] = {0, 32, 16, 48};
+	rect[1] = {16, 32, 32, 48};
+	rect[2] = {32, 32, 48, 48};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 2;
+
+			if (Random(0, 1))
+				npc->xm = Random(-0x200, -0x100);
+			else
+				npc->xm = Random(0x100, 0x200);
+
+			if (Random(0, 1))
+				npc->ym = Random(-0x200, -0x100);
+			else
+				npc->ym = Random(0x100, 0x200);
+
+			npc->xm2 = npc->xm;
+			npc->ym2 = npc->ym;
+			// Fallthrough
+		case 1:
+			if ( ++npc->ani_no > 2 )
+				npc->ani_no = 1;
+
+			break;
+	}
+
+	if (npc->xm2 < 0 && npc->flag & 1)
+		npc->xm2 = -npc->xm2;
+	if (npc->xm2 > 0 && npc->flag & 4)
+		npc->xm2 = -npc->xm2;
+
+	if (npc->ym2 < 0 && npc->flag & 2)
+		npc->ym2 = -npc->ym2;
+	if (npc->ym2 > 0 && npc->flag & 8)
+		npc->ym2 = -npc->ym2;
+
+	if (npc->xm2 > 0x200)
+		npc->xm2 = 0x200;
+	if (npc->xm2 < -0x200)
+		npc->xm2 = -0x200;
+
+	if (npc->ym2 > 0x200)
+		npc->ym2 = 0x200;
+	if (npc->ym2 < -0x200)
+		npc->ym2 = -0x200;
+
+	if (npc->shock)
+	{
+		npc->x += npc->xm2 / 2;
+		npc->y += npc->ym2 / 2;
+	}
+	else
+	{
+		npc->x += npc->xm2;
+		npc->y += npc->ym2;
+	}
+
+	npc->rect = rect[npc->ani_no];
+}
+
 //H/V Trigger
 void ActNpc046(NPCHAR *npc)
 {
@@ -438,6 +687,109 @@
 	npc->rect = rect[0];
 }
 
+//Sandcroc
+void ActNpc047(NPCHAR *npc)
+{
+	switch ( npc->act_no )
+	{
+		case 0:
+			npc->ani_no = 0;
+			npc->act_no = 1;
+			npc->act_wait = 0;
+			npc->tgt_y = npc->y;
+			npc->bits &= ~0x20;
+			npc->bits &= ~4;
+			npc->bits &= ~1;
+			npc->bits &= ~8;
+			// Fallthrough
+		case 1:
+			if (gMC.x > npc->x - 0x1000 && gMC.x < npc->x + 0x1000 && gMC.y > npc->y && gMC.y < npc->y + 0x1000)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				PlaySoundObject(102, 1);
+			}
+
+			if (gMC.x > npc->x)
+				npc->x += 0x400;
+
+			if (gMC.x < npc->x)
+				npc->x -= 0x400;
+
+			break;
+
+		case 2:
+			if (++npc->ani_wait > 3)
+			{
+				++npc->ani_no;
+				npc->ani_wait = 0;
+			}
+
+			if (npc->ani_no == 3)
+				npc->damage = 10;
+
+			if (npc->ani_no == 4)
+			{
+				npc->bits |= 0x20;
+				npc->act_no = 3;
+				npc->act_wait = 0;
+			}
+
+			break;
+
+		case 3:
+			npc->bits |= 1;
+			npc->damage = 0;
+			++npc->act_wait;
+
+			if (npc->shock)
+			{
+				npc->act_no = 4;
+				npc->act_wait = 0;
+			}
+
+			break;
+
+		case 4:
+			npc->bits |= 8;
+			npc->y += 0x200;
+
+			if (++npc->act_wait == 32)
+			{
+				npc->bits &= ~1;
+				npc->bits &= ~0x20;
+				npc->act_no = 5;
+				npc->act_wait = 0;
+			}
+
+			break;
+
+		case 5:
+			if (npc->act_wait < 100)
+			{
+				++npc->act_wait;
+			}
+			else
+			{
+				npc->y = npc->tgt_y;
+				npc->ani_no = 0;
+				npc->act_no = 0;
+			}
+
+			break;
+	}
+
+	RECT rect[5];
+
+	rect[0] = {0, 48, 48, 80};
+	rect[1] = {48, 48, 96, 80};
+	rect[2] = {96, 48, 144, 80};
+	rect[3] = {144, 48, 192, 80};
+	rect[4] = {192, 48, 240, 80};
+
+	npc->rect = rect[npc->ani_no];
+}
+
 //Omega projectiles
 void ActNpc048(NPCHAR *npc)
 {
@@ -498,6 +850,573 @@
 		npc->rect = rcLeft[npc->ani_no];
 }
 
+//Skullhead
+void ActNpc049(NPCHAR *npc)
+{
+	if (npc->act_no >= 10 && npc->pNpc->code_char == 3)
+	{
+		npc->act_no = 3;
+		npc->xm = 0;
+		npc->ym = 0;
+		npc->count2 = 1;
+	}
+
+	if (npc->flag & 1)
+	{
+		npc->direct = 2;
+		npc->xm = 0x100;
+	}
+
+	if (npc->flag & 4)
+	{
+		npc->direct = 0;
+		npc->xm = -0x100;
+	}
+
+	switch (npc->act_no)
+	{
+		case 0:
+			if (npc->pNpc)
+				npc->act_no = 10;
+			else
+				npc->act_no = 1;
+			// Fallthrough
+		case 1:
+			if (++npc->act_wait > 3)
+			{
+				npc->ym = -0x400;
+				npc->act_no = 3;
+				npc->ani_no = 2;
+
+				if (npc->count2 == 0)
+				{
+					if (npc->direct == 0)
+						npc->xm = -0x100;
+					else
+						npc->xm = 0x100;
+				}
+				else
+				{
+					if (npc->direct == 0)
+						npc->xm = -0x200;
+					else
+						npc->xm = 0x200;
+				}
+			}
+
+			npc->ani_no = 1;
+			break;
+
+		case 3:
+			if (npc->flag & 8)
+			{
+				npc->act_no = 1;
+				npc->act_wait = 0;
+				npc->xm = 0;
+			}
+
+			if (npc->flag & 8 || npc->ym > 0)
+				npc->ani_no = 1;
+			else
+				npc->ani_no = 2;
+
+			break;
+
+		case 10:
+			if (npc->count1 < 50)
+			{
+				++npc->count1;
+			}
+			else
+			{
+				if (gMC.x > npc->x - 0x10000 && gMC.x < npc->x + 0x10000 && gMC.y > npc->y - 0xC000 && gMC.y < npc->y + 0xC000)
+				{
+					npc->act_no = 11;
+					npc->act_wait = 0;
+					npc->ani_no = 2;
+				}
+			}
+
+			break;
+
+		case 11:
+			if (++npc->act_wait == 30 || npc->act_wait == 35)
+			{
+				const unsigned char deg = GetArktan(npc->x - gMC.x, npc->y + 0x800 - gMC.y);
+				const int ym = 2 * GetSin(deg);
+				const int xm = 2 * GetCos(deg);
+				SetNpChar(50, npc->x, npc->y, xm, ym, 0, 0, 0x100);
+				PlaySoundObject(39, 1);
+			}
+
+			if (npc->act_wait > 50)
+			{
+				npc->count1 = 0;
+				npc->act_no = 10;
+				npc->ani_no = 1;
+			}
+
+			break;
+	}
+
+	if (npc->act_no >= 10)
+	{
+		npc->x = npc->pNpc->x;
+		npc->y = npc->pNpc->y + 0x2000;
+		npc->direct = npc->pNpc->direct;
+		--npc->pNpc->count1;
+	}
+
+	npc->ym += 0x40;
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	RECT rcLeft[3];
+	RECT rcRight[3];
+
+	rcLeft[0] = {0, 80, 32, 104};
+	rcLeft[1] = {32, 80, 64, 104};
+	rcLeft[2] = {64, 80, 96, 104};
+
+	rcRight[0] = {0, 104, 32, 128};
+	rcRight[1] = {32, 104, 64, 128};
+	rcRight[2] = {64, 104, 96, 128};
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Skeleton projectile
+void ActNpc050(NPCHAR *npc)
+{
+	switch (npc->act_no)
+	{
+		case 0:
+			if (npc->direct == 2)
+			{
+				npc->act_no = 2;
+			}
+			// Fallthrough
+		case 1:
+			npc->x += npc->xm;
+			npc->y += npc->ym;
+
+			if (npc->flag & 1)
+			{
+				npc->act_no = 2;
+				npc->xm = 0x200;
+				++npc->count1;
+			}
+
+			if (npc->flag & 4)
+			{
+				npc->act_no = 2;
+				npc->xm = -0x200;
+				++npc->count1;
+			}
+
+			if (npc->flag & 2)
+			{
+				npc->act_no = 2;
+				npc->ym = 0x200;
+				++npc->count1;
+			}
+
+			if (npc->flag & 8)
+			{
+				npc->act_no = 2;
+				npc->ym = -0x200;
+				++npc->count1;
+			}
+
+			break;
+
+		case 2:
+			npc->ym += 0x40;
+
+			npc->x += npc->xm;
+			npc->y += npc->ym;
+
+			if (npc->flag & 8)
+			{
+				if (++npc->count1 > 1)
+				{
+					SetCaret(npc->x, npc->y, 2, 0);
+					npc->cond = 0;
+				}
+			}
+
+			break;
+	}
+
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+	if (npc->ym < -0x5FF)
+		npc->ym = -0x5FF;
+
+	RECT rect[4];
+
+	rect[0] = {48, 32, 64, 48};
+	rect[1] = {64, 32, 80, 48};
+	rect[2] = {80, 32, 96, 48};
+	rect[3] = {96, 32, 112, 48};
+
+	if (npc->direct == 0)
+	{
+		if (++npc->ani_wait > 1)
+		{
+			npc->ani_wait = 0;
+			++npc->ani_no;
+		}
+
+		if (npc->ani_no > 3)
+			npc->ani_no = 0;
+	}
+	else
+	{
+		if (++npc->ani_wait > 1)
+		{
+			npc->ani_wait = 0;
+			--npc->ani_no;
+		}
+
+		if (npc->ani_no < 0)
+			npc->ani_no = 3;
+	}
+
+	npc->rect = rect[npc->ani_no];
+}
+
+//Crow & Skullhead
+void ActNpc051(NPCHAR *npc)
+{
+	switch (npc->act_no)
+	{
+		case 0:
+			if (gMC.x > npc->x - (WINDOW_WIDTH * 0x200) && gMC.x < npc->x + (WINDOW_WIDTH * 0x200) && gMC.y > npc->y - (WINDOW_WIDTH * 0x200) && gMC.y < npc->y + (WINDOW_WIDTH * 0x200))
+			{
+				npc->tgt_x = npc->x;
+				npc->tgt_y = npc->y;
+				npc->ym = 0x400;
+				npc->act_no = 1;
+				SetNpChar(49, 0, 0, 0, 0, 0, npc, 0);
+			}
+			else
+				break;
+
+			// Fallthrough
+		case 1:
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			if (npc->tgt_y < npc->y)
+				npc->ym -= 10;
+			if (npc->tgt_y > npc->y)
+				npc->ym += 10;
+
+			if (npc->ym > 0x200)
+				npc->ym = 0x200;
+			if (npc->ym < -0x200)
+				npc->ym = -0x200;
+
+			if (npc->count1 < 10)
+				++npc->count1;
+			else
+				npc->act_no = 2;
+
+			break;
+
+		case 2:
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			if (npc->y > gMC.y + 0x4000)
+			{
+				if (gMC.x < npc->x)
+					npc->xm += 0x10;
+				if (gMC.x > npc->x)
+					npc->xm -= 0x10;
+			}
+			else
+			{
+				if (gMC.x < npc->x)
+					npc->xm -= 0x10;
+				if (gMC.x > npc->x)
+					npc->xm += 0x10;
+			}
+
+			if (gMC.y < npc->y)
+				npc->ym -= 0x10;
+			if (gMC.y > npc->y)
+				npc->ym += 0x10;
+
+			if (npc->shock)
+			{
+				npc->ym += 0x20;
+				npc->xm = 0;
+			}
+
+			break;
+	}
+
+	if (npc->xm < 0 && npc->flag & 1)
+		npc->xm = 0x100;
+	if (npc->xm > 0 && npc->flag & 4)
+		npc->xm = -0x100;
+
+	if (npc->ym < 0 && npc->flag & 2)
+		npc->ym = 0x100;
+	if (npc->ym > 0 && npc->flag & 8)
+		npc->ym = -0x100;
+
+	if (npc->xm > 0x400)
+		npc->xm = 0x400;
+	if (npc->xm < -0x400)
+		npc->xm = -0x400;
+
+	if (npc->ym > 0x200)
+		npc->ym = 0x200;
+	if (npc->ym < -0x200)
+		npc->ym = -0x200;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	RECT rect_left[5];
+	RECT rect_right[5];
+
+	rect_left[0] = {96, 80, 128, 112};
+	rect_left[1] = {128, 80, 160, 112};
+	rect_left[2] = {160, 80, 192, 112};
+	rect_left[3] = {192, 80, 224, 112};
+	rect_left[4] = {224, 80, 256, 112};
+
+	rect_right[0] = {96, 112, 128, 144};
+	rect_right[1] = {128, 112, 160, 144};
+	rect_right[2] = {160, 112, 192, 144};
+	rect_right[3] = {192, 112, 224, 144};
+	rect_right[4] = {224, 112, 256, 144};
+
+	if (npc->shock)
+	{
+		npc->ani_no = 4;
+	}
+	else if (npc->act_no == 2 && npc->y < gMC.y - 0x4000)
+	{
+		npc->ani_no = 0;
+	}
+	else
+	{
+		if (npc->act_no)
+		{
+			if (++npc->ani_wait > 1)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 1)
+				npc->ani_no = 0;
+		}
+	}
+
+	if (npc->direct == 0)
+		npc->rect = rect_left[npc->ani_no];
+	else
+		npc->rect = rect_right[npc->ani_no];
+}
+
+//Bliue robot (sitting)
+void ActNpc052(NPCHAR *npc)
+{
+	RECT rect[1];
+
+	rect[0] = {240, 96, 256, 112};
+
+	npc->rect = rect[0];
+}
+
+//Skullstep leg
+void ActNpc053(NPCHAR *npc)
+{
+	RECT rcLeft[2];
+	RECT rcRight[2];
+
+	rcLeft[0] = {0, 128, 24, 144};
+	rcLeft[1] = {24, 128, 48, 144};
+
+	rcRight[0] = {48, 128, 72, 144};
+	rcRight[1] = {72, 128, 96, 144};
+
+	if (npc->pNpc->code_char == 3)
+	{
+		VanishNpChar(npc);
+		SetDestroyNpChar(npc->x, npc->y, npc->view.back, 4);
+		return;
+	}
+
+	unsigned char deg;
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->count1 = 10;
+			// Fallthrough
+		case 1:
+			if (npc->direct == 0 && npc->flag & 0x20)
+			{
+				npc->pNpc->y -= 0x400;
+				npc->pNpc->ym -= 0x100;
+			}
+
+			if (npc->direct == 2 && npc->flag & 0x10)
+			{
+				npc->pNpc->y -= 0x400;
+				npc->pNpc->ym -= 0x100;
+			}
+
+			if (npc->flag & 8)
+			{
+				npc->pNpc->y -= 0x400;
+				npc->pNpc->ym -= 0x100;
+
+				if (npc->pNpc->direct == 0)
+					npc->pNpc->xm -= 0x80;
+				else
+					npc->pNpc->xm += 0x80;
+			}
+
+			deg = npc->xm + npc->pNpc->count2;
+			npc->x = npc->pNpc->x + npc->count1 * GetCos(deg);
+			npc->y = npc->pNpc->y + npc->count1 * GetSin(deg);
+			npc->direct = npc->pNpc->direct;
+			break;
+	}
+
+	npc->direct = npc->pNpc->direct;
+	npc->ani_no = deg < 20 || deg > 108;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Skullstep
+void ActNpc054(NPCHAR *npc)
+{
+	RECT rcLeft[3];
+	RECT rcRight[3];
+
+	rcLeft[0] = {0, 80, 32, 104};
+	rcLeft[1] = {32, 80, 64, 104};
+	rcLeft[2] = {64, 80, 96, 104};
+
+	rcRight[0] = {0, 104, 32, 128};
+	rcRight[1] = {32, 104, 64, 128};
+	rcRight[2] = {64, 104, 96, 128};
+
+	unsigned char deg;
+	switch (npc->act_no)
+	{
+		case 0:
+			SetNpChar(53, 0, 0, 0, 0, npc->direct, npc, 0x100);
+			SetNpChar(53, 0, 0, 128, 0, npc->direct, npc, 0);
+			npc->act_no = 1;
+			npc->ani_no = 1;
+			// Fallthrough
+		case 1:
+			deg = npc->count2;
+
+			if (npc->direct == 0)
+				deg -= 6;
+			else
+				deg += 6;
+
+			npc->count2 = deg;
+
+			if (npc->flag & 8)
+			{
+				npc->xm = 3 * npc->xm / 4;
+
+				if (++npc->act_wait > 60)
+				{
+					npc->act_no = 2;
+					npc->act_wait = 0;
+				}
+			}
+			else
+			{
+				npc->act_wait = 0;
+			}
+
+			if (npc->direct == 0 && npc->flag & 1)
+			{
+				if (++npc->count1 > 8)
+				{
+					npc->direct = 2;
+					npc->xm = -npc->xm;
+				}
+			}
+			else if (npc->direct == 2 && npc->flag & 4)
+			{
+				if (++npc->count1 > 8)
+				{
+					npc->direct = 0;
+					npc->xm = -npc->xm;
+				}
+			}
+			else
+			{
+				npc->count1 = 0;
+			}
+
+			break;
+
+		case 2:
+			++npc->act_wait;
+			npc->shock += npc->act_wait;
+
+			if (npc->act_wait > 50)
+			{
+				VanishNpChar(npc);
+				SetDestroyNpChar(npc->x, npc->y, npc->view.back, 8);
+				PlaySoundObject(25, 1);
+			}
+
+			break;
+	}
+
+	npc->ym += 0x80;
+
+	if (npc->xm > 0x2FF)
+		npc->xm = 0x2FF;
+	if (npc->xm < -0x2FF)
+		npc->xm = -0x2FF;
+
+	if (npc->ym > 0x2FF)
+		npc->ym = 0x2FF;
+	if (npc->ym < -0x2FF)
+		npc->ym = -0x2FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
 //Cairn
 void ActNpc055(NPCHAR *npc)
 {
@@ -678,6 +1597,162 @@
 		npc->rect = rcLeft[npc->ani_no];
 	else
 		npc->rect = rcRight[npc->ani_no];
+}
+
+//Crow
+void ActNpc057(NPCHAR *npc)
+{
+	unsigned char deg;
+	switch (npc->act_no)
+	{
+		case 0:
+			deg = Random(0, 0xFF);
+			npc->xm = GetCos(deg);
+			npc->tgt_x = npc->x + 8 * GetCos(deg + 0x40);
+
+			deg = Random(0, 0xFF);
+			npc->ym = GetSin(deg);
+			npc->tgt_y = npc->y + 8 * GetSin(deg + 0x40);
+
+			npc->act_no = 1;
+			npc->count1 = 120;
+			npc->ani_no = Random(0, 1);
+			npc->ani_wait = Random(0, 4);
+			// Fallthrough
+		case 1:
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			if (npc->tgt_x < npc->x)
+				npc->xm -= 0x10;
+			if (npc->tgt_x > npc->x)
+				npc->xm += 0x10;
+
+			if (npc->tgt_y < npc->y)
+				npc->ym -= 0x10;
+			if (npc->tgt_y > npc->y)
+				npc->ym += 0x10;
+
+			if (npc->xm > 0x200)
+				npc->xm = 0x200;
+			if (npc->xm < -0x200)
+				npc->xm = -0x200;
+
+			if (npc->ym > 0x200)
+				npc->ym = 0x200;
+			if (npc->ym < -0x200)
+				npc->ym = -0x200;
+
+			if (npc->shock)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+
+				if (npc->direct == 2)
+					npc->xm = -0x200;
+				else
+					npc->xm = 0x200;
+
+				npc->ym = 0;
+			}
+
+			break;
+
+		case 2:
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			if (npc->y > gMC.y + 0x6000)
+			{
+				if (gMC.x < npc->x)
+					npc->xm += 0x10;
+				if (gMC.x > npc->x)
+					npc->xm -= 0x10;
+			}
+			else
+			{
+				if (gMC.x < npc->x)
+					npc->xm -= 0x10;
+				if (gMC.x > npc->x)
+					npc->xm += 0x10;
+			}
+
+			if (gMC.y < npc->y)
+				npc->ym -= 0x10;
+			if (gMC.y > npc->y)
+				npc->ym += 0x10;
+
+			if (npc->shock)
+			{
+				npc->ym += 0x20;
+				npc->xm = 0;
+			}
+
+			if (npc->xm < 0 && npc->flag & 1)
+				npc->xm = 0x200;
+			if (npc->xm > 0 && npc->flag & 4)
+				npc->xm = -0x200;
+
+			if (npc->ym < 0 && npc->flag & 2)
+				npc->ym = 0x200;
+			if (npc->ym > 0 && npc->flag & 8)
+				npc->ym = -0x200;
+
+			if (npc->xm > 0x5FF)
+				npc->xm = 0x5FF;
+			if (npc->xm < -0x5FF)
+				npc->xm = -0x5FF;
+
+			if (npc->ym > 0x5FF)
+				npc->ym = 0x5FF;
+			if (npc->ym < -0x5FF)
+				npc->ym = -0x5FF;
+
+			break;
+	}
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	RECT rect_left[5];
+	RECT rect_right[5];
+
+	rect_left[0] = {96, 80, 128, 112};
+	rect_left[1] = {128, 80, 160, 112};
+	rect_left[2] = {160, 80, 192, 112};
+	rect_left[3] = {192, 80, 224, 112};
+	rect_left[4] = {224, 80, 256, 112};
+
+	rect_right[0] = {96, 112, 128, 144};
+	rect_right[1] = {128, 112, 160, 144};
+	rect_right[2] = {160, 112, 192, 144};
+	rect_right[3] = {192, 112, 224, 144};
+	rect_right[4] = {224, 112, 256, 144};
+
+	if (npc->shock)
+	{
+		npc->ani_no = 4;
+	}
+	else
+	{
+		if (++npc->ani_wait > 1)
+		{
+			npc->ani_wait = 0;
+			++npc->ani_no;
+		}
+
+		if (npc->ani_no > 1)
+			npc->ani_no = 0;
+	}
+
+	if (npc->direct == 0)
+		npc->rect = rect_left[npc->ani_no];
+	else
+		npc->rect = rect_right[npc->ani_no];
 }
 
 //Basu (Egg Corridor)
--- a/src/NpcAct120.cpp
+++ b/src/NpcAct120.cpp
@@ -9,6 +9,9 @@
 #include "Back.h"
 #include "Triangle.h"
 #include "Caret.h"
+#include "KeyControl.h"
+#include "Frame.h"
+#include "Bullet.h"
 
 //Colon (1)
 void ActNpc120(NPCHAR *npc)
@@ -339,6 +342,58 @@
 	npc->rect = rect[npc->direct];
 }
 
+//Sunstone
+void ActNpc124(NPCHAR *npc)
+{
+	RECT rect[2];
+
+	rect[0] = {160, 0, 192, 32};
+	rect[1] = {192, 0, 224, 32};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->x += 0x1000;
+			npc->y += 0x1000;
+			// Fallthrough
+		case 1:
+			npc->bits &= ~8;
+			npc->ani_no = 0;
+			break;
+
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 1;
+			npc->act_wait = 0;
+			npc->bits |= 8;
+			// Fallthrough
+		case 11:
+			switch (npc->direct)
+			{
+				case 0:
+					npc->x -= 0x80;
+					break;
+				case 1:
+					npc->y -= 0x80;
+					break;
+				case 2:
+					npc->x += 0x80;
+					break;
+				case 3:
+					npc->y += 0x80;
+					break;
+			}
+			if (++npc->act_wait % 8 == 0)
+				PlaySoundObject(26, 1);
+
+			SetQuake(20);
+			break;
+	}
+
+	npc->rect = rect[npc->ani_no];
+}
+
 //Hidden item
 void ActNpc125(NPCHAR *npc)
 {
@@ -366,6 +421,137 @@
 		npc->rect = rc[1];
 }
 
+//Puppy (running)
+void ActNpc126(NPCHAR *npc)
+{
+	RECT rcLeft[6];
+	RECT rcRight[6];
+
+	rcLeft[0] = {48, 144, 64, 160};
+	rcLeft[1] = {64, 144, 80, 160};
+	rcLeft[2] = {48, 144, 64, 160};
+	rcLeft[3] = {80, 144, 96, 160};
+	rcLeft[4] = {96, 144, 112, 160};
+	rcLeft[5] = {112, 144, 128, 160};
+
+	rcRight[0] = {48, 160, 64, 176};
+	rcRight[1] = {64, 160, 80, 176};
+	rcRight[2] = {48, 160, 64, 176};
+	rcRight[3] = {80, 160, 96, 176};
+	rcRight[4] = {96, 160, 112, 176};
+	rcRight[5] = {112, 160, 128, 176};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 1:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			if (gMC.x > npc->x - 0xC000 && gMC.x < npc->x + 0xC000 && gMC.y > npc->y - 0x4000 && gMC.y < npc->y + 0x2000)
+			{
+				if (gMC.x < npc->x)
+					npc->direct = 0;
+				else
+					npc->direct = 2;
+			}
+
+			if (gMC.x > npc->x - 0x4000 && gMC.x < npc->x + 0x4000 && gMC.y > npc->y - 0x4000 && gMC.y < npc->y + 0x2000)
+			{
+				if (gMC.x < npc->x)
+					npc->direct = 2;
+				else
+					npc->direct = 0;
+
+				npc->act_no = 10;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 1;
+				npc->ani_no = 0;
+			}
+
+			break;
+
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 4;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 11:
+			if (npc->flag & 8)
+			{
+				if (++npc->ani_wait > 2)
+				{
+					npc->ani_wait = 0;
+					++npc->ani_no;
+				}
+
+				if (npc->ani_no > 5)
+					npc->ani_no = 4;
+			}
+			else
+			{
+				npc->ani_no = 5;
+				npc->ani_wait = 0;
+			}
+
+			if (npc->xm < 0 && npc->flag & 1)
+			{
+				npc->xm /= -2;
+				npc->direct = 2;
+			}
+
+			if (npc->xm > 0 && npc->flag & 4)
+			{
+				npc->xm /= -2;
+				npc->direct = 0;
+			}
+
+			if (npc->direct == 0)
+				npc->xm -= 0x40;
+			else
+				npc->xm += 0x40;
+
+			if (npc->xm > 0x5FF)
+				npc->xm = 0x400;
+
+			if (npc->xm < -0x5FF)
+				npc->xm = -0x400;
+
+			break;
+	}
+
+	if (gKeyTrg & gKeyDown)
+		npc->bits |= 0x2000;
+	else
+		npc->bits &= ~0x2000;
+
+	npc->ym += 0x40;
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
 //Machine gun trail (Level 2)
 void ActNpc127(NPCHAR *npc)
 {
@@ -489,4 +675,742 @@
 	npc->y += npc->ym;
 	
 	npc->rect = rect[npc->ani_no + 3 * npc->direct];
+}
+
+//Puppy (sitting, wagging tail)
+void ActNpc130(NPCHAR *npc)
+{
+	RECT rcLeft[4];
+	RECT rcRight[4];
+
+	rcLeft[0] = {48, 144, 64, 160};
+	rcLeft[1] = {64, 144, 80, 160};
+	rcLeft[2] = {48, 144, 64, 160};
+	rcLeft[3] = {80, 144, 96, 160};
+
+	rcRight[0] = {48, 160, 64, 176};
+	rcRight[1] = {64, 160, 80, 176};
+	rcRight[2] = {48, 160, 64, 176};
+	rcRight[3] = {80, 160, 96, 176};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			npc->bits |= 0x2000;
+			// Fallthrough
+		case 1:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			if (gMC.x > npc->x - 0x8000 && gMC.x < npc->x + 0x8000 && gMC.y > npc->y - 0x4000 && gMC.y < npc->y + 0x2000)
+			{
+				if (++npc->ani_wait > 3)
+				{
+					npc->ani_wait = 0;
+					++npc->ani_no;
+				}
+
+				if (npc->ani_no > 3)
+					npc->ani_no = 2;
+			}
+
+			if (gMC.x > npc->x - 0xC000 && gMC.x < npc->x + 0xC000 && gMC.y > npc->y - 0x4000 && gMC.y < npc->y + 0x2000)
+			{
+				if (gMC.x < npc->x)
+					npc->direct = 0;
+				else
+					npc->direct = 2;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 1;
+				npc->ani_no = 0;
+			}
+
+			break;
+	}
+
+	npc->ym += 0x40;
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Puppy (sleeping)
+void ActNpc131(NPCHAR *npc)
+{
+	RECT rcLeft[1];
+	RECT rcRight[1];
+
+	rcLeft[0] = {144, 144, 160, 160};
+	rcRight[0] = {144, 160, 160, 176};
+
+	if (++npc->act_wait > 100)
+	{
+		npc->act_wait = 0;
+		SetCaret(npc->x, npc->y, 5, 0);
+	}
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Puppy (barking)
+void ActNpc132(NPCHAR *npc)
+{
+	RECT rcLeft[5];
+	RECT rcRight[5];
+
+	rcLeft[0] = {48, 144, 64, 160};
+	rcLeft[1] = {64, 144, 80, 160};
+	rcLeft[2] = {96, 144, 112, 160};
+	rcLeft[3] = {96, 144, 112, 160};
+	rcLeft[4] = {128, 144, 144, 160};
+
+	rcRight[0] = {48, 160, 64, 176};
+	rcRight[1] = {64, 160, 80, 176};
+	rcRight[2] = {96, 160, 112, 176};
+	rcRight[3] = {96, 160, 112, 176};
+	rcRight[4] = {128, 160, 144, 176};
+
+	if (npc->act_no < 100)
+	{
+		if (gMC.x < npc->x)
+			npc->direct = 0;
+		else
+			npc->direct = 2;
+	}
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 1:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			if (gMC.x > npc->x - 0x8000 && gMC.x < npc->x + 0x8000 && gMC.y > npc->y - 0x2000 && gMC.y < npc->y + 0x2000)
+			{
+				if (++npc->ani_wait > 4)
+				{
+					npc->ani_wait = 0;
+					++npc->ani_no;
+				}
+
+				if (npc->ani_no > 4)
+					npc->ani_no = 2;
+
+				if (npc->ani_no == 4 && npc->ani_wait == 0)
+					PlaySoundObject(105, 1);
+			}
+			else
+			{
+				if (npc->ani_no == 4)
+					npc->ani_no = 2;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 1;
+				npc->ani_no = 0;
+			}
+
+			break;
+
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 11:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 12;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			break;
+
+		case 12:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 11;
+				npc->ani_no = 0;
+			}
+
+			break;
+
+		case 100:
+			npc->act_no = 101;
+			npc->count1 = 0;
+			// Fallthrough
+		case 101:
+			if (++npc->ani_wait > 4)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 4)
+			{
+				if (npc->count1 < 3)
+				{
+					npc->ani_no = 2;
+					++npc->count1;
+				}
+				else
+				{
+					npc->ani_no = 0;
+					npc->count1 = 0;
+				}
+			}
+
+			if (npc->ani_no == 4 && npc->ani_wait == 0)
+				PlaySoundObject(105, 1);
+
+			break;
+
+		case 120:
+			npc->ani_no = 0;
+			break;
+	}
+
+	npc->ym += 0x40;
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Jenka
+void ActNpc133(NPCHAR *npc)
+{
+	RECT rcLeft[2];
+	RECT rcRight[2];
+
+	rcLeft[0] = {176, 32, 192, 48};
+	rcLeft[1] = {192, 32, 208, 48};
+
+	rcRight[0] = {176, 48, 192, 64};
+	rcRight[1] = {192, 48, 208, 64};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 1:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 1;
+				npc->ani_no = 0;
+			}
+
+			break;
+	}
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Armadillo
+void ActNpc134(NPCHAR *npc)
+{
+	RECT rcLeft[3];
+	RECT rcRight[3];
+
+	rcLeft[0] = {224, 0, 256, 16};
+	rcLeft[1] = {256, 0, 288, 16};
+	rcLeft[2] = {288, 0, 320, 16};
+
+	rcRight[0] = {224, 16, 256, 32};
+	rcRight[1] = {256, 16, 288, 32};
+	rcRight[2] = {288, 16, 320, 32};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 2;
+			npc->bits &= ~0x20;
+			npc->bits |= 4;
+			// Fallthrough
+		case 1:
+			if (gMC.x > npc->x - 0x28000 && gMC.x < npc->x + 0x28000 && gMC.y > npc->y - 0x14000 && gMC.y < npc->y + 0x8000)	// TODO: Maybe do something about this for widescreen/tallscreen?
+			{
+				npc->act_no = 10;
+				npc->bits |= 0x20;
+				npc->bits &= ~4;
+			}
+
+			break;
+
+		case 10:
+			if (++npc->ani_wait > 4)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 1)
+				npc->ani_no = 0;
+
+			if (npc->direct == 0 && npc->flag & 1)
+				npc->direct = 2;
+			if (npc->direct == 2 && npc->flag & 4)
+				npc->direct = 0;
+
+			if (npc->direct == 0)
+				npc->x -= 0x100;
+			else
+				npc->x += 0x100;
+
+			if (CountArmsBullet(6))
+			{
+				npc->act_no = 20;
+				npc->act_wait = 0;
+				npc->ani_no = 2;
+				npc->bits &= ~0x20;
+				npc->bits |= 4;
+			}
+
+			break;
+
+		case 20:
+			if (++npc->act_wait > 100)
+			{
+				npc->act_no = 10;
+				npc->ani_no = 0;
+				npc->ani_wait = 0;
+				npc->bits |= 0x20;
+				npc->bits &= ~4;
+			}
+
+			break;
+	}
+
+	npc->ym += 0x40;
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Skeleton
+void ActNpc135(NPCHAR *npc)
+{
+	RECT rcRight[2];
+	RECT rcLeft[2];
+
+	rcLeft[0] = {256, 32, 288, 64};
+	rcLeft[1] = {288, 32, 320, 64};
+
+	rcRight[0] = {256, 64, 288, 96};
+	rcRight[1] = {288, 64, 320, 96};
+
+	if (gMC.x < npc->x - 0x2C000 || gMC.x > npc->x + 0x2C000 || gMC.y < npc->y - 0x14000 || gMC.y > npc->y + 0x8000)
+		npc->act_no = 0;
+
+	switch ( npc->act_no )
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->xm = 0;
+			// Fallthrough
+		case 1:
+			if (gMC.x > npc->x - 0x28000 && gMC.x < npc->x + 0x28000 && gMC.y > npc->y - 0x14000 && gMC.y < npc->y + 0x8000)
+				npc->act_no = 10;
+
+			if (npc->flag & 8)
+				npc->ani_no = 0;
+
+			break;
+
+		case 10:
+			npc->xm = 0;
+			npc->act_no = 11;
+			npc->act_wait = 0;
+			npc->ani_no = 0;
+			// Fallthrough
+		case 11:
+			if (++npc->act_wait >= 5 && npc->flag & 8)
+			{
+				npc->act_no = 20;
+				npc->ani_no = 1;
+				npc->count1 = 0;
+				npc->ym = -0x200 * Random(1, 3);
+
+				if (npc->shock == 0)
+				{
+					if (gMC.x > npc->x)
+						npc->xm += 0x100;
+					else
+						npc->xm -= 0x100;
+				}
+				else
+				{
+					if (gMC.x > npc->x)
+						npc->xm -= 0x100;
+					else
+						npc->xm += 0x100;
+				}
+			}
+
+			break;
+
+		case 20:
+			if (npc->ym > 0 && npc->count1 == 0)
+			{
+				++npc->count1;
+				const unsigned char deg = GetArktan(npc->x - gMC.x, npc->y + 0x800 - gMC.y);
+				const int ym = 2 * GetSin(deg);
+				const int xm = 2 * GetCos(deg);
+				SetNpChar(50, npc->x, npc->y, xm, ym, 0, 0, 0x180);
+				PlaySoundObject(39, 1);
+			}
+
+			if (npc->flag & 8)
+			{
+				npc->act_no = 10;
+				npc->ani_no = 0;
+			}
+
+			break;
+	}
+
+	if (npc->act_no >= 10)
+	{
+		if (gMC.x < npc->x)
+			npc->direct = 0;
+		else
+			npc->direct = 2;
+	}
+
+	npc->ym += 0x33;
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+
+	if (npc->xm > 0x5FF)
+		npc->xm = 0x5FF;
+	if (npc->xm < -0x5FF)
+		npc->xm = -0x5FF;
+
+	npc->y += npc->ym;
+	npc->x += npc->xm;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Puppy (carried)
+void ActNpc136(NPCHAR *npc)
+{
+	RECT rcLeft[2];
+	RECT rcRight[2];
+
+	rcLeft[0] = {48, 144, 64, 160};
+	rcLeft[1] = {64, 144, 80, 160};
+
+	rcRight[0] = {48, 160, 64, 176};
+	rcRight[1] = {64, 160, 80, 176};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->bits &= ~0x2000;
+			npc->act_no = 1;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 1:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 1;
+				npc->ani_no = 0;
+			}
+
+			break;
+	}
+
+	if (gMC.direct == 0)
+		npc->direct = 0;
+	else
+		npc->direct = 2;
+
+	npc->y = gMC.y - 0x1400;
+
+	if (npc->direct == 0)
+	{
+		npc->x = gMC.x + 0x800;
+		npc->rect = rcLeft[npc->ani_no];
+	}
+	else
+	{
+		npc->x = gMC.x - 0x800;
+		npc->rect = rcRight[npc->ani_no];
+	}
+
+	if (gMC.ani_no % 2)
+		++npc->rect.top;
+}
+
+//Large door (frame)
+void ActNpc137(NPCHAR *npc)
+{
+	RECT rc[1];
+
+	rc[0] = {96, 136, 128, 188};
+
+	npc->rect = rc[0];
+}
+
+//Large door (door)
+void ActNpc138(NPCHAR *npc)
+{
+	RECT rcLeft[1];
+	RECT rcRight[1];
+
+	rcLeft[0] = {96, 112, 112, 136};
+	rcRight[0] = {112, 112, 128, 136};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+
+			if (npc->direct == 0)
+			{
+				npc->rect = rcLeft[0];
+				npc->x += 0x1000;
+			}
+			else
+			{
+				npc->rect = rcRight[0];
+				npc->x -= 0x1000;
+			}
+
+			npc->tgt_x = npc->x;
+			break;
+
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 1;
+			npc->act_wait = 0;
+			npc->bits |= 8;
+			// Fallthrough
+		case 11:
+			if (++npc->act_wait % 8 == 0)
+				PlaySoundObject(26, 1);
+
+			if (npc->direct == 0)
+			{
+				npc->rect = rcLeft[0];
+				npc->rect.left += npc->act_wait / 8;
+			}
+			else
+			{
+				npc->x = npc->tgt_x + ((npc->act_wait / 8) * 0x200);
+				npc->rect = rcRight[0];
+				npc->rect.right -= npc->act_wait / 8;
+			}
+
+			if (npc->act_wait == 104)
+				npc->cond = 0;
+
+			break;
+	}
+}
+
+//Doctor
+void ActNpc139(NPCHAR *npc)
+{
+	RECT rcLeft[3];
+	RECT rcRight[3];
+
+	rcLeft[0] = {0, 128, 24, 160};
+	rcLeft[1] = {24, 128, 48, 160};
+	rcLeft[2] = {48, 128, 72, 160};
+
+	rcRight[0] = {0, 160, 24, 192};
+	rcRight[1] = {24, 160, 48, 192};
+	rcRight[2] = {48, 160, 72, 192};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->xm = 0;
+			npc->ym = 0;
+			npc->y -= 0x1000;
+			// Fallthrough
+		case 1:
+			if (npc->flag & 8)
+				npc->ani_no = 0;
+			else
+				npc->ani_no = 2;
+
+			npc->ym += 0x40;
+			break;
+
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 1;
+			npc->ani_wait = 0;
+			npc->count1 = 0;
+			// Fallthrough
+		case 11:
+			if (++npc->ani_wait > 6)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 1)
+			{
+				npc->ani_no = 0;
+				++npc->count1;
+			}
+
+			if (npc->count1 > 8)
+			{
+				npc->ani_no = 0;
+				npc->act_no = 1;
+			}
+
+			break;
+
+		case 20:
+			npc->act_no = 21;
+			npc->act_wait = 0;
+			npc->ani_no = 2;
+			npc->tgt_y = npc->y - 0x4000;
+			// Fallthrough
+		case 21:
+			if (npc->y < npc->tgt_y)
+				npc->ym += 0x20;
+			else
+				npc->ym -= 0x20;
+
+			if (npc->ym > 0x200)
+				npc->ym = 0x200;
+			if (npc->ym < -0x200)
+				npc->ym = -0x200;
+
+			break;
+
+		case 30:
+			npc->act_no = 31;
+			npc->xm = 0;
+			npc->ym = 0;
+			npc->act_wait = 2 * (npc->rect.bottom - npc->rect.top);
+			PlaySoundObject(29, 1);
+			// Fallthrough
+		case 31:
+			--npc->act_wait;
+			npc->ani_no = 0;
+
+			if (npc->act_wait == 0)
+				npc->cond = 0;
+
+			break;
+
+		case 40:
+			npc->act_no = 41;
+			npc->act_wait = 0;
+			npc->xm = 0;
+			npc->ym = 0;
+			PlaySoundObject(29, 1);
+			// Fallthrough
+		case 41:
+			npc->ani_no = 2;
+
+			if (++npc->act_wait >= 64)
+				npc->act_no = 20;
+
+			break;
+	}
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+
+	if (npc->act_no == 31 || npc->act_no == 41)
+	{
+		npc->rect.bottom = npc->rect.top + npc->act_wait / 2;
+
+		if (npc->act_wait / 2 % 2)
+			++npc->rect.left;
+	}
 }
--- a/src/NpcAct140.cpp
+++ b/src/NpcAct140.cpp
@@ -8,7 +8,654 @@
 #include "Sound.h"
 #include "Back.h"
 #include "Triangle.h"
+#include "Caret.h"
+#include "Frame.h"
+#include "Flash.h"
+#include "Bullet.h"
 
+//Toroko (frenzied)
+void ActNpc140(NPCHAR *npc)
+{
+	RECT rcLeft[14];
+	RECT rcRight[14];
+
+	rcLeft[0] = {0, 0, 32, 32};
+	rcLeft[1] = {32, 0, 64, 32};
+	rcLeft[2] = {64, 0, 96, 32};
+	rcLeft[3] = {96, 0, 128, 32};
+	rcLeft[4] = {128, 0, 160, 32};
+	rcLeft[5] = {160, 0, 192, 32};
+	rcLeft[6] = {192, 0, 224, 32};
+	rcLeft[7] = {224, 0, 256, 32};
+	rcLeft[8] = {0, 64, 32, 96};
+	rcLeft[9] = {32, 64, 64, 96};
+	rcLeft[10] = {64, 64, 96, 96};
+	rcLeft[11] = {96, 64, 128, 96};
+	rcLeft[12] = {128, 64, 160, 96};
+	rcLeft[13] = {0, 0, 0, 0};
+
+	rcRight[0] = {0, 32, 32, 64};
+	rcRight[1] = {32, 32, 64, 64};
+	rcRight[2] = {64, 32, 96, 64};
+	rcRight[3] = {96, 32, 128, 64};
+	rcRight[4] = {128, 32, 160, 64};
+	rcRight[5] = {160, 32, 192, 64};
+	rcRight[6] = {192, 32, 224, 64};
+	rcRight[7] = {224, 32, 256, 64};
+	rcRight[8] = {0, 96, 32, 128};
+	rcRight[9] = {32, 96, 64, 128};
+	rcRight[10] = {64, 96, 96, 128};
+	rcRight[11] = {96, 96, 128, 128};
+	rcRight[12] = {128, 96, 160, 128};
+	rcRight[13] = {0, 0, 0, 0};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 9;
+			npc->act_wait = 0;
+			npc->bits &= ~0x2000;
+			// Fallthrough
+		case 1:
+			if (++npc->act_wait > 50)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+				npc->ani_no = 8;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->ani_no > 10)
+				npc->ani_no = 9;
+
+			if (++npc->act_wait > 50)
+			{
+				npc->act_no = 3;
+				npc->act_wait = 0;
+				npc->ani_no = 0;
+			}
+
+			break;
+
+		case 3:
+			if (++npc->act_wait > 50)
+			{
+				npc->act_no = 10;
+				npc->bits |= 0x20;
+			}
+
+			break;
+
+		case 10:
+			npc->bits = npc->bits;
+			npc->act_no = 11;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			npc->act_wait = Random(20, 130);
+			npc->xm = 0;
+			// Fallthrough
+		case 11:
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			if (++npc->ani_wait > 4)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 1)
+				npc->ani_no = 0;
+
+			if (CountArmsBullet(6) || CountArmsBullet(3) > 3)
+				npc->act_no = 20;
+
+			if (npc->act_wait)
+			{
+				--npc->act_wait;
+			}
+			else
+			{
+				if (Random(0, 99) % 2)
+					npc->act_no = 20;
+				else
+					npc->act_no = 50;
+			}
+
+			break;
+
+		case 20:
+			npc->act_no = 21;
+			npc->ani_no = 2;
+			npc->act_wait = 0;
+			// Fallthrough
+		case 21:
+			if (++npc->act_wait > 10)
+			{
+				npc->act_no = 22;
+				npc->act_wait = 0;
+				npc->ani_no = 3;
+				npc->ym = -0x5FF;
+
+				if (npc->direct == 0)
+					npc->xm = -0x200u;
+				else
+					npc->xm = 0x200;
+			}
+
+			break;
+
+		case 22:
+			if (++npc->act_wait > 10)
+			{
+				npc->act_no = 23;
+				npc->act_wait = 0;
+				npc->ani_no = 6;
+				SetNpChar(141, 0, 0, 0, 0, 0, npc, 0);
+			}
+
+			break;
+
+		case 23:
+			if (++npc->act_wait > 30)
+			{
+				npc->act_no = 24;
+				npc->act_wait = 0;
+				npc->ani_no = 7;
+			}
+
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			break;
+
+		case 24:
+			if (++npc->act_wait > 3)
+			{
+				npc->act_no = 25;
+				npc->ani_no = 3;
+			}
+
+			break;
+
+		case 25:
+			if (npc->flag & 8)
+			{
+				npc->act_no = 26;
+				npc->act_wait = 0;
+				npc->ani_no = 2;
+				PlaySoundObject(26, 1);
+				SetQuake(20);
+			}
+
+			break;
+
+		case 26:
+			npc->xm = 8 * npc->xm / 9;
+
+			if (++npc->act_wait > 20)
+			{
+				npc->act_no = 10;
+				npc->ani_no = 0;
+			}
+
+			break;
+
+		case 50:
+			npc->act_no = 51;
+			npc->act_wait = 0;
+			npc->ani_no = 4;
+			SetNpChar(141, 0, 0, 0, 0, 0, npc, 0);
+			// Fallthrough
+		case 51:
+			if (++npc->act_wait > 30)
+			{
+				npc->act_no = 52;
+				npc->act_wait = 0;
+				npc->ani_no = 5;
+			}
+
+			if (gMC.x < npc->x)
+				npc->direct = 0;
+			else
+				npc->direct = 2;
+
+			break;
+
+		case 52:
+			if (++npc->act_wait > 3)
+			{
+				npc->act_no = 10;
+				npc->ani_no = 0;
+			}
+
+			break;
+
+		case 100:
+			npc->ani_no = 3;
+			npc->act_no = 101;
+			npc->bits &= ~0x20;
+			npc->damage = 0;
+
+			for (int i = 0; i < 8; ++i)
+				SetNpChar(4, npc->x + (Random(-12, 12) * 0x200), npc->y + (Random(-12, 12) * 0x200), Random(-341, 341), Random(-0x600u, 0), 0, 0, 0x100);
+
+			break;
+
+		case 101:
+			if (npc->flag & 8)
+			{
+				npc->act_no = 102;
+				npc->act_wait = 0;
+				npc->ani_no = 2;
+				PlaySoundObject(26, 1);
+				SetQuake(20);
+			}
+
+			break;
+
+		case 102:
+			npc->xm = 8 * npc->xm / 9;
+
+			if (++npc->act_wait > 50)
+			{
+				npc->act_no = 103;
+				npc->act_wait = 0;
+				npc->ani_no = 10;
+			}
+
+			break;
+
+		case 103:
+			if (++npc->act_wait > 50)
+			{
+				npc->ani_no = 9;
+				npc->act_no = 104;
+				npc->act_wait = 0;
+			}
+
+			break;
+
+		case 104:
+			if (++npc->ani_no > 10)
+				npc->ani_no = 9;
+
+			if (++npc->act_wait > 100)
+			{
+				npc->act_wait = 0;
+				npc->ani_no = 9;
+				npc->act_no = 105;
+			}
+
+			break;
+
+		case 105:
+			if (++npc->act_wait > 50)
+			{
+				npc->ani_wait = 0;
+				npc->act_no = 106;
+				npc->ani_no = 11;
+			}
+
+			break;
+
+		case 106:
+			if (++npc->ani_wait > 50)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 12)
+				npc->ani_no = 12;
+
+			break;
+
+		case 140:
+			npc->act_no = 141;
+			npc->act_wait = 0;
+			npc->ani_no = 12;
+			PlaySoundObject(29, 1);
+			// Fallthrough
+		case 141:
+			if (++npc->ani_no > 13)
+				npc->ani_no = 12;
+
+			if (++npc->act_wait > 100)
+			{
+				for (int i = 0; i < 4; ++i)
+					SetNpChar(4, npc->x + (Random(-12, 12) * 0x200), npc->y + (Random(-12, 12) * 0x200), Random(-341, 341), Random(-0x600, 0), 0, 0, 0x100);
+
+				npc->cond = 0;
+			}
+
+			break;
+	}
+
+	if (npc->act_no > 100 && npc->act_no < 105 && npc->act_wait % 9 == 0)
+		SetNpChar(4, npc->x + (Random(-12, 12) * 0x200), npc->y + (Random(-12, 12) * 0x200), Random(-341, 341), Random(-0x600, 0), 0, 0, 0x100);
+
+	npc->ym += 0x20;
+
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+	if (npc->ym < -0x5FF)
+		npc->ym = -0x5FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+// Toroko block projectile
+void ActNpc141(NPCHAR *npc)
+{
+	RECT rect[2]; // [sp+8h] [bp-24h]@1
+
+	rect[0] = {288, 32, 304, 48};
+	rect[1] = {304, 32, 320, 48};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->act_wait = 0;
+			// Fallthrough
+		case 1:
+			if (npc->pNpc->direct == 0)
+				npc->x = npc->pNpc->x + 0x1400;
+			else
+				npc->x = npc->pNpc->x - 0x1400;
+
+			npc->y = npc->pNpc->y - 0x1000;
+
+			if (npc->pNpc->act_no == 24 || npc->pNpc->act_no == 52)
+			{
+				npc->act_no = 10;
+
+				if (npc->pNpc->direct == 0)
+					npc->x = npc->pNpc->x - 0x2000;
+				else
+					npc->x = npc->pNpc->x + 0x2000;
+
+				npc->y = npc->pNpc->y;
+
+				const unsigned char deg = GetArktan(npc->x - gMC.x, npc->y - gMC.y);
+				npc->ym = 4 * GetSin(deg);
+				npc->xm = 4 * GetCos(deg);
+
+				PlaySoundObject(39, 1);
+			}
+
+			break;
+
+		case 10:
+			if (npc->flag & 0xF)
+			{
+				npc->act_no = 20;
+				npc->act_wait = 0;
+				SetCaret(npc->x, npc->y, 2, 0);
+				PlaySoundObject(12, 1);
+
+				for (int i = 0; i < 4; ++i)
+					SetNpChar(4, npc->x, npc->y, Random(-0x200, 0x200), Random(-0x200, 0x200), 0, 0, 0x100);
+			}
+			else
+			{
+				npc->x += npc->xm;
+				npc->y += npc->ym;
+			}
+
+			break;
+
+		case 20:
+			npc->x += npc->xm;
+			npc->y += npc->ym;
+
+			if (++npc->act_wait > 4)
+			{
+				for (int i = 0; i < 4; ++i)
+					SetNpChar(4, npc->x, npc->y, Random(-0x200, 0x200), Random(-0x200, 0x200), 0, 0, 0x100);
+
+				npc->code_char = 142;
+				npc->ani_no = 0;
+				npc->act_no = 20;
+				npc->xm = 0;
+				npc->bits &= ~4;
+				npc->bits |= 0x20;
+				npc->damage = 1;
+			}
+
+			break;
+	}
+
+	if (++npc->ani_no > 1)
+		npc->ani_no = 0;
+
+	npc->rect = rect[npc->ani_no];
+}
+
+// Flower Cub
+void ActNpc142(NPCHAR *npc)
+{
+	RECT rect[5];
+
+	rect[0] = {0, 128, 16, 144};
+	rect[1] = {16, 128, 32, 144};
+	rect[2] = {32, 128, 48, 144};
+	rect[3] = {48, 128, 64, 144};
+	rect[4] = {64, 128, 80, 144};
+
+	switch (npc->act_no)
+	{
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 0;
+			npc->act_wait = 0;
+			// Fallthrough
+		case 11:
+			if (++npc->act_wait > 30)
+			{
+				npc->act_no = 12;
+				npc->ani_no = 1;
+				npc->ani_wait = 0;
+			}
+
+			break;
+
+		case 12:
+			if (++npc->ani_wait > 8)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no == 3)
+			{
+				npc->act_no = 20;
+				npc->ym = -0x200;
+
+				if (gMC.x < npc->x)
+					npc->xm = -0x200;
+				else
+					npc->xm = 0x200;
+			}
+
+			break;
+
+		case 20:
+			if (npc->ym > -0x80)
+				npc->ani_no = 4;
+			else
+				npc->ani_no = 3;
+
+			if (npc->flag & 8)
+			{
+				npc->ani_no = 2;
+				npc->act_no = 21;
+				npc->act_wait = 0;
+				npc->xm = 0;
+				PlaySoundObject(23, 1);
+			}
+
+			break;
+
+		case 21:
+			if (++npc->act_wait > 10)
+			{
+				npc->act_no = 10;
+				npc->ani_no = 0;
+			}
+
+			break;
+	}
+
+	npc->ym += 0x40;
+
+	if (npc->ym > 0x5FF)
+		npc->ym = 0x5FF;
+	if (npc->ym < -0x5FF)
+		npc->ym = -0x5FF;
+
+	npc->x += npc->xm;
+	npc->y += npc->ym;
+
+	npc->rect = rect[npc->ani_no];
+}
+
+// Jenka (collapsed)
+void ActNpc143(NPCHAR *npc)
+{
+	RECT rcLeft[1];
+	RECT rcRight[1];
+
+	rcLeft[0] = {208, 32, 224, 48};
+
+	rcRight[0] = {208, 48, 224, 64};
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+}
+
+//Toroko (teleporting in)
+void ActNpc144(NPCHAR *npc)
+{
+	RECT rcLeft[5];
+	RECT rcRight[5];
+
+	rcLeft[0] = {0, 64, 16, 80};
+	rcLeft[1] = {16, 64, 32, 80};
+	rcLeft[2] = {32, 64, 48, 80};
+	rcLeft[3] = {16, 64, 32, 80};
+	rcLeft[4] = {128, 64, 144, 80};
+
+	rcRight[0] = {0, 80, 16, 96};
+	rcRight[1] = {16, 80, 32, 96};
+	rcRight[2] = {32, 80, 48, 96};
+	rcRight[3] = {16, 80, 32, 96};
+	rcRight[4] = {128, 80, 144, 96};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			npc->tgt_x = npc->x;
+			PlaySoundObject(29, 1);
+			// Fallthrough
+		case 1:
+			if (++npc->act_wait == 64)
+			{
+				npc->act_no = 2;
+				npc->act_wait = 0;
+			}
+
+			break;
+
+		case 2:
+			if (++npc->ani_wait > 2)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no > 3)
+				npc->ani_no = 2;
+
+			if (npc->flag & 8)
+			{
+				npc->act_no = 4;
+				npc->act_wait = 0;
+				npc->ani_no = 4;
+				PlaySoundObject(23, 1);
+			}
+
+			break;
+
+		case 10:
+			npc->act_no = 11;
+			npc->ani_no = 0;
+			npc->ani_wait = 0;
+			// Fallthrough
+		case 11:
+			if (Random(0, 120) == 10)
+			{
+				npc->act_no = 12;
+				npc->act_wait = 0;
+				npc->ani_no = 1;
+			}
+
+			break;
+
+		case 12:
+			if (++npc->act_wait > 8)
+			{
+				npc->act_no = 11;
+				npc->ani_no = 0;
+			}
+
+			break;
+	}
+
+	if (npc->act_no > 1)
+	{
+		npc->ym += 0x20;
+		if (npc->ym > 0x5FF)
+			npc->ym = 0x5FF;
+
+		npc->y += npc->ym;
+	}
+
+	if (npc->direct == 0)
+		npc->rect = rcLeft[npc->ani_no];
+	else
+		npc->rect = rcRight[npc->ani_no];
+
+	if (npc->act_no == 1)
+	{
+		npc->rect.bottom = npc->rect.top + npc->act_wait / 4;
+
+		if (npc->act_wait / 2 % 2)
+			npc->x = npc->tgt_x;
+		else
+			npc->x = npc->tgt_x + 0x200;
+	}
+}
+
 //King's sword
 void ActNpc145(NPCHAR *npc)
 {
@@ -47,6 +694,56 @@
 		npc->rect = rcLeft[npc->ani_no];
 	else
 		npc->rect = rcRight[npc->ani_no];
+}
+
+//Lightning
+void ActNpc146(NPCHAR *npc)
+{
+	RECT rect[5];
+
+	rect[0] = {0, 0, 0, 0};
+	rect[1] = {256, 0, 272, 240};
+	rect[2] = {272, 0, 288, 240};
+	rect[3] = {288, 0, 304, 240};
+	rect[4] = {304, 0, 320, 240};
+
+	switch (npc->act_no)
+	{
+		case 0:
+			npc->act_no = 1;
+
+			if (npc->direct == 2)
+				SetFlash(0, 0, 2);
+			// Fallthrough
+		case 1:
+			if (++npc->act_wait > 10)
+			{
+				npc->act_no = 2;
+				PlaySoundObject(101, 1);
+			}
+
+			break;
+
+		case 2:
+			if (++npc->ani_wait > 2)
+			{
+				npc->ani_wait = 0;
+				++npc->ani_no;
+			}
+
+			if (npc->ani_no == 2)
+				npc->damage = 10;
+
+			if (npc->ani_no > 4)
+			{
+				SetDestroyNpChar(npc->x, npc->y, 0x1000, 8);
+				npc->cond = 0;
+			}
+
+			break;
+	}
+
+	npc->rect = rect[npc->ani_no];
 }
 
 //Quote
--- a/src/NpcAct280.cpp
+++ b/src/NpcAct280.cpp
@@ -8,6 +8,13 @@
 #include "Sound.h"
 #include "Back.h"
 #include "Triangle.h"
+#include "Frame.h"
+
+//Quake
+void ActNpc292(NPCHAR *npc)
+{
+	SetQuake(10);
+}
 
 //Doctor (opening)
 void ActNpc298(NPCHAR *npc)
--- a/src/NpcAct300.cpp
+++ b/src/NpcAct300.cpp
@@ -9,6 +9,7 @@
 #include "Back.h"
 #include "Triangle.h"
 #include "Caret.h"
+#include "Boss.h"
 
 //Demon crown (opening)
 void ActNpc300(NPCHAR *npc)
@@ -29,4 +30,72 @@
 		SetCaret(npc->x + (Random(-8, 8) * 0x200), npc->y + 0x1000, 13, 1);
 
 	npc->rect = rc[0];
+}
+
+//Camera focus marker
+void ActNpc302(NPCHAR *npc)
+{
+	switch (npc->act_no)
+	{
+		case 10:
+			npc->x = gMC.x;
+			npc->y = gMC.y - 0x4000;
+			break;
+
+		case 20:
+			switch (npc->direct)
+			{
+				case 0:
+					npc->x -= 0x400;
+					break;
+				case 1:
+					npc->y -= 0x400;
+					break;
+				case 2:
+					npc->x += 0x400;
+					break;
+				case 3:
+					npc->y += 0x400;
+					break;
+			}
+
+			gMC.x = npc->x;
+			gMC.y = npc->y;
+			break;
+
+		case 30:
+			npc->x = gMC.x;
+			npc->y = gMC.y + 0xA000;
+			break;
+
+		case 100:
+			npc->act_no = 101;
+
+			if (npc->direct)
+			{
+				int i;
+				for (i = 0xAA; i < 0x200; ++i)
+				{
+					if (gNPC[i].cond & 0x80 && gNPC[i].code_event == npc->direct)
+					{
+						npc->pNpc = &gNPC[i];
+						break;
+					}
+				}
+				if (i == 0x200)
+				{
+					npc->cond = 0;
+					break;
+				}
+			}
+			else
+			{
+				npc->pNpc = gBoss;
+			}
+			// Fallthrough
+		case 101:
+			npc->x = (npc->pNpc->x + gMC.x) / 2;
+			npc->y = (npc->pNpc->y + gMC.y) / 2;
+			break;
+	}
 }
--- a/src/NpcTbl.cpp
+++ b/src/NpcTbl.cpp
@@ -100,20 +100,20 @@
 	ActNpc041,
 	ActNpc042,
 	ActNpc043,
-	nullptr,
-	nullptr,
+	ActNpc044,
+	ActNpc045,
 	ActNpc046,
-	nullptr,
+	ActNpc047,
 	ActNpc048,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
+	ActNpc049,
+	ActNpc050,
+	ActNpc051,
+	ActNpc052,
+	ActNpc053,
+	ActNpc054,
 	ActNpc055,
 	ActNpc056,
-	nullptr,
+	ActNpc057,
 	ActNpc058,
 	ActNpc059,
 	ActNpc060,
@@ -180,32 +180,32 @@
 	ActNpc121,
 	ActNpc122,
 	ActNpc123,
-	nullptr,
+	ActNpc124,
 	ActNpc125,
-	nullptr,
+	ActNpc126,
 	ActNpc127,
 	ActNpc128,
 	ActNpc129,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
-	nullptr,
+	ActNpc130,
+	ActNpc131,
+	ActNpc132,
+	ActNpc133,
+	ActNpc134,
+	ActNpc135,
+	ActNpc136,
+	ActNpc137,
+	ActNpc138,
+	ActNpc139,
+	ActNpc140,
+	ActNpc141,
+	ActNpc142,
+	ActNpc143,
+	ActNpc144,
 	ActNpc145,
+	ActNpc146,
 	nullptr,
 	nullptr,
 	nullptr,
-	nullptr,
 	ActNpc150,
 	ActNpc151,
 	nullptr,
@@ -348,17 +348,17 @@
 	nullptr,
 	nullptr,
 	nullptr,
+	ActNpc292,
 	nullptr,
 	nullptr,
 	nullptr,
 	nullptr,
 	nullptr,
-	nullptr,
 	ActNpc298,
 	ActNpc299,
 	ActNpc300,
 	nullptr,
-	nullptr,
+	ActNpc302,
 	nullptr,
 	nullptr,
 	nullptr,