objects/oItem/step.gml
From spelunky.gmk, Spelunky Classic 1.1's source, © 2008, 2009 Derek Yu and Mossmouth, LLC, shown whole under the Spelunky User License v1.1b. Extracted by spelunky.ai's tools, an unofficial fan project, one file per script or event; the // ==== lines are the extractor's, naming each action of the event. Some scripts are others' work that Derek Yu credits in the source's readme.txt: Martin Piecyk's platform engine, ChevyRay's view scaling scripts and tsg1zzn's Super Sound System.
oItem's step event, 400 lines of GML.
if ((x > view_xview[0]-16 and x < view_xview[0] + view_wview[0]+16 and y > view_yview[0]-16 and y < view_yview[0] + view_hview[0]+16) or type == "Rope"){ if (global.hasSpectacles) depth = 51; else depth = 101; if ((not instance_exists(oShopkeeper) or global.thiefLevel > 0 or global.murderer) and cost > 0) { if (isRealLevel()) global.itemsStolen += 1; cost = 0; forSale = false; } // stealing makes shopkeeper angry if (isRealLevel()) { if (cost > 0 and forSale and not isInShop(x, y)) { global.itemsStolen += 1; scrShopkeeperAnger(0); cost = 0; } } else if (isLevel()) { if (cost > 0 and forSale and not isInShop(x, y)) { scrShopkeeperAnger(0); cost = 0; } } else cost = 0; if (held) { xVel = 0; yVel = 0; if (oPlayer1.facing == LEFT) x = oPlayer1.x - 4; if (oPlayer1.facing == RIGHT) x = oPlayer1.x + 4; if (heavy) { if (type == "Gold Idol" or type == "Crystal Skull" or type == "Lamp" or type == "Damsel") { if (oPlayer1.state == DUCKING and abs(oPlayer1.xVel) < 2) y = oPlayer1.y+2; else y = oPlayer1.y; } else { if (oPlayer1.state == DUCKING and abs(oPlayer1.xVel) < 2) y = oPlayer1.y-2; else y = oPlayer1.y-4; } } else { if (oPlayer1.state == DUCKING and abs(oPlayer1.xVel) < 2) y = oPlayer1.y + 4; else y = oPlayer1.y+2; } depth = 1; if (oPlayer1.holdItem == 0) { held = false; } } else if (not collision_point(x, y, oSolid, 0, 0)) { moveTo(xVel, yVel); colLeft = false; colRight = false; colBot = false; colTop = false; if (isCollisionLeft(1)) colLeft = true; if (isCollisionRight(1)) colRight = true; if (isCollisionBottom(1)) colBot = true; if (isCollisionTop(1)) colTop = true; if (not colLeft and not colRight) stuck = false; if (not colBot and not stuck) yVel += myGrav; if (yVel > 8) yVel = 8; if (colLeft or colRight) { xVel = -xVel * 0.5; myGrav = 0.6; } if (colBot) { myGrav = 0.6; // bounce if (yVel > 1) yVel = -yVel * bounceFactor; else yVel = 0; // friction if (abs(xVel) < 0.1) xVel = 0; else if (abs(xVel) != 0) xVel *= frictionFactor; if (abs(yVel) < 1) { y -= 1; if (not isCollisionBottom(1)) y += 1; yVel = 0; } } if (sticky and type == "Bomb" and sprite_index = sBombArmed) { if (colLeft or colRight or colTop or colBot) { xVel = 0; yVel = 0; if (colBot and abs(yVel) < 1) y += 1; } } else if (type == "Arrow" and abs(xVel) > 6) { if (colLeft) { x -= 2; xVel = 0; yVel = 0; } else if (colRight) { x += 2; xVel = 0; yVel = 0; } stuck = true; } else if (colLeft and not stuck) { if (not colRight) x += 1; //yVel = 0; } else if (colRight and not stuck) { x -= 1; //yVel = 0; } if (sticky and type == "Bomb" and sprite_index = sBombArmed) { // do nothing } else if (isCollisionTop(1)) { if (yVel < 0) yVel = -yVel * 0.8; else y += 1; myGrav = 0.6; } if (collision_rectangle(x-3, y-3, x+3, y+3, oLava, 0, 0)) { myGrav = 0; xVel = 0; yVel = 0; y += 0.05; } else { myGrav = 0.6; } if (collision_point(x, y-5, oLava, 0, 0) and type != "Sceptre") { if (type == "Bomb") { instance_create(x, y, oExplosion); repeat(3) { instance_create(x, y, oFlame); } playSound(global.sndExplosion); } instance_destroy(); } } else { colLeft = false; colRight = false; colBot = false; colTop = false; if (isCollisionLeft(1)) colLeft = true; if (isCollisionRight(1)) colRight = true; if (isCollisionBottom(1)) colBot = true; if (isCollisionTop(1)) colTop = true; if (colTop and !colBot) { y += 1; } else if (colLeft and !colRight) { x += 1; } else if (colRight and !colLeft) { x -= 1; } else { xVel = 0; yVel = 0; } } if (type == "Bomb" and sticky) { if (abs(xVel) > 2 or abs(yVel) > 2 and collision_rectangle(x-2, y-2, x+2, y+2, oEnemy, 0, 0) and enemyID == 0) { enemyID = instance_nearest(x, y, oEnemy); /* if (enemyID.bombID) { // Can only have one sticky bomb on someone at a time with enemyID.bombID { sticky = false; enemyID = 0; } } */ enemyID.bombID = self; // instance_nearest(x, y, oBomb); stickyXDiff = enemyID.x-x; stickyYDiff = enemyID.y-y; } else if (abs(xVel) > 2 or abs(yVel) > 2 and collision_rectangle(x-2, y-2, x+2, y+2, oDamsel, 0, 0) and enemyID == 0) { enemyID = collision_rectangle(x-2, y-2, x+2, y+2, oDamsel, 0, 0); /* if (enemyID.bombID) { // Can only have one sticky bomb on someone at a time with enemyID.bombID { sticky = false; enemyID = 0; } } */ enemyID.bombID = self; // instance_nearest(x, y, oBomb); stickyXDiff = enemyID.x-x; stickyYDiff = enemyID.y-y; } } else if (abs(xVel) > 2 or abs(yVel) > 2) { if (collision_rectangle(x-2, y-2, x+2, y+2, oEnemy, 0, 0)) { obj = instance_nearest(x, y, oEnemy); if (not obj.invincible and obj.type != "Magma Man") { obj.xVel = xVel; // vampires are weak to "stakes" if (type == "Arrow" and obj.status != 98 and obj.type == "Vampire") obj.hp -= 3; with obj { if (type == "Caveman" or type == "ManTrap" or type == "Vampire" or type == "Yeti" or type == "Hawkman") { if (status != STUNNED) { if (type == "Caveman" or type == "Vampire" or type == "Yeti" or type == "Hawkman") { scrCreateBlood(x+8, y+8, 1); } else if (type == "ManTrap") { instance_create(x+rand(0,16), y-8+rand(0,16), oLeaf); } hp -= 1; status = STUNNED; counter = stunTime; yVel = -6; playSound(global.sndHit); } } else if (type == "Shopkeeper") { if (status < 98) { scrCreateBlood(x, y, 1); hp -= 1; yVel = -6; status = 2; playSound(global.sndHit); } } else if (type == "Giant Spider") { if (whipped == 0) { scrCreateBlood(x+16, y+24, 1); hp -= 1; whipped = 10; playSound(global.sndHit); } } else if (type == "Tomb Lord") { if (whipped == 0) { scrCreateBlood(x+16, y+16, 1); hp -= 1; whipped = 20; playSound(global.sndHit); } } else if (type == "Alien Boss") { if (status != 99 and sprite_index != sAlienBossHurt) { scrCreateBlood(x+8, y+8, 1); hp -= 1; sprite_index = sAlienBossHurt; image_speed = 0.8; playSound(global.sndHit); } } else if (type == "UFO") { instance_create(x+8, y+8, oExplosion); playSound(global.sndExplosion); if (rand(1,3) == 1) instance_create(x+8, y+8, oAlienEject); if (isRealLevel()) global.enemyKills[16] += 1; global.ufos += 1; global.kills += 1; instance_destroy(); } else { scrCreateBlood(x+8, y+8, 1); hp -= 1; origX = x; origY = y; playSound(global.sndHit); } } obj.xVel = xVel * 0.3; if (type == "Arrow" and sprite_index = sBombArrowRight) { instance_create(x, y, oExplosion); if (global.graphicsHigh) scrCreateFlame(x, y, 3); } if (type == "Arrow" or type == "Fish Bone") { instance_destroy(); } } } if (collision_rectangle(x-2, y-2, x+2, y+2, oDamsel, false, true)) { obj = collision_rectangle(x-2, y-2, x+2, y+2, oDamsel, false, true); if (not obj.invincible and obj.status != 99 and obj.hit == 0) { if (not (obj.held and safe)) { scrCreateBlood(obj.x, obj.y, 1); with obj { if (held) { held = false; with oPlayer1 { holdItem = 0; pickupItemType = ""; } } hp -= 1; yVel = -6; status = 2; counter = 120; hit = 10; } obj.xVel = xVel * 0.3; if (type == "Arrow" or type == "Fish Bone") instance_destroy(); playSound(global.sndHit); if (obj.forSale) { scrShopkeeperAnger(3); } } } } }}